奋斗
努力

单台云服务器上同时部署MySQL和Redis的最佳实践是什么?

云计算

在单台云服务器上同时部署 MySQL 和 Redis(即“共存部署”)虽常见于开发、测试或轻量级生产场景(如小型网站、内部工具、POC),但需谨慎权衡性能、稳定性与可维护性。以下是经过验证的最佳实践指南,兼顾安全性、资源隔离、稳定性和可观测性:


✅ 一、前提判断:是否真的需要共存?

场景 推荐做法
开发/测试/CI环境 ✅ 合理,节省成本,便于本地复现
日均 PV < 1万、QPS < 50 的轻量生产应用(如企业官网、后台管理系统) ⚠️ 可接受,但必须严格遵循下述实践
高并发、核心交易系统、数据强一致性要求场景 强烈不推荐 —— 应分离部署(至少 MySQL 单独,Redis 可选集群)

🔔 关键提醒:MySQL 和 Redis 对内存、I/O、CPU 的争用高度敏感,共存易引发“雪崩式干扰”(如 Redis 内存满触发 OOM Killer 杀死 MySQL 进程)。


✅ 二、核心最佳实践(按优先级排序)

1. 资源硬隔离:CPU + 内存 + I/O

  • CPU 绑核(推荐)

    # 为 MySQL 分配 CPU 0-1,Redis 分配 CPU 2-3(4核机器)
    systemctl edit mysqld
    # 添加:
    [Service]
    CPUAffinity=0 1
    CPUSchedulingPolicy=fifo
    
    systemctl edit redis-server
    # 添加:
    [Service]
    CPUAffinity=2 3
    CPUSchedulingPolicy=fifo
  • 内存限制(强制!)

    • MySQLinnodb_buffer_pool_size ≤ 总内存 × 50%(建议 40–55%,留足 OS+Redis 缓存)
      例:16GB 内存 → innodb_buffer_pool_size = 6G
    • Redismaxmemory 必须显式设置(不可为 no0),并启用 maxmemory-policy allkeys-lru
      例:16GB 内存 → maxmemory 3gb(预留充足内存给 OS/MySQL/文件缓存)
    • OS 层限制(推荐 systemd)
      
      # /etc/systemd/system/mysqld.service.d/limits.conf
      [Service]
      MemoryLimit=8G
      CPUQuota=70%

    /etc/systemd/system/redis-server.service.d/limits.conf

    [Service]
    MemoryLimit=4G
    CPUQuota=30%

2. 存储与 I/O 隔离

  • 磁盘分离(关键!)
    • MySQL 数据目录(/var/lib/mysql)→ 专用 SSD 磁盘(或独立挂载点)
    • Redis 持久化(RDB/AOF)→ 另一块 SSD 或 /tmpfs(若禁用持久化)
    • ❌ 禁止共用同一块机械盘或根分区(避免 I/O 争抢导致 MySQL 响应延迟飙升)
  • I/O 调度优化
    # MySQL 数据盘(SSD)使用 none/noop 调度器
    echo 'none' > /sys/block/nvme0n1/queue/scheduler
    # Redis 持久化盘同理

3. 网络与端口安全

  • 绑定指定网卡/IP(避免暴露内网):

    # my.cnf
    bind-address = 127.0.0.1        # 或内网IP(如 192.168.1.10)
    skip-networking = OFF           # 若需远程访问,配合防火墙
    
    # redis.conf
    bind 127.0.0.1                  # 禁用 0.0.0.0!
    protected-mode yes              # 强制开启
    requirepass your_strong_password # 必设密码(Redis 6+ 支持 ACL)
  • 防火墙白名单
    ufw allow from 192.168.1.0/24 to any port 3306  # 仅允许内网应用访问 MySQL
    ufw allow from 192.168.1.0/24 to any port 6379  # Redis 同理

4. 配置调优要点

组件 关键参数 推荐值(16GB内存示例) 说明
MySQL innodb_buffer_pool_size 6G 最大内存占用项,勿超 55%
innodb_log_file_size 512M 提升写性能,但需停机调整
max_connections 200 避免连接数爆炸耗尽内存
Redis maxmemory 3gb 必须设!
maxmemory-policy allkeys-lru 避免 OOM Kill
tcp-keepalive 300 防止连接假死
save "" (禁用 RDB) 若无需持久化,彻底关闭 RDB;否则 save 900 1
appendonly no 生产环境慎用 AOF(I/O 压力大)

5. 监控与告警(不可省略)

  • 必监指标
    • ✅ 内存使用率(free -h, systemd-cgtop
    • ✅ MySQL Threads_connected, Innodb_buffer_pool_wait_free, Slow_queries
    • ✅ Redis used_memory, evicted_keys, rejected_connections, latency
  • 推荐工具
    • Prometheus + Grafana(采集 mysqld_exporter + redis_exporter
    • 日志集中:Filebeat → ELK 或 Loki
    • 告警阈值示例:
    • Redis used_memory > 90% of maxmemory → 立即告警
    • MySQL Threads_connected > 90% of max_connections → 告警

6. 备份与故障恢复

  • MySQL 备份
    • 使用 mysqldump --single-transaction(InnoDB)或 mydumper(并发快)
    • 避开 Redis RDB/AOF fork 时间段(fork 会复制进程页表,加剧内存压力)
  • Redis 备份
    • 若启用 RDB:bgsave 手动触发后同步 .rdb 文件(注意磁盘空间)
    • 禁止在业务高峰执行 bgsavebgrewriteaof
  • 一键切换脚本(应急):
    # stop-redis-if-mysql-stressed.sh
    if [[ $(mysql -Nse "SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME='THREADS_CONNECTED'") -gt 180 ]]; then
      systemctl stop redis-server
    fi

⚠️ 三、绝对禁止事项(血泪教训)

行为 风险 替代方案
❌ 不设 maxmemory Redis 内存无限增长 → 触发 Linux OOM Killer 杀死 MySQL ✅ 强制配置 maxmemory + maxmemory-policy
❌ MySQL 和 Redis 共用 / 分区且无磁盘配额 一个服务日志/持久化撑爆磁盘 → 全服务宕机 ✅ 独立挂载点 + df -h 监控 + logrotate
❌ Redis 开放 0.0.0.0:6379 且无密码 10分钟内被X_X木马劫持 bind 127.0.0.1 + 密码 + 防火墙
❌ 在同一台机器跑 MySQL 主从 + Redis I/O 和内存双重压垮 ✅ 至少将从库/Redis 拆到其他节点

📈 四、扩展建议(当业务增长时)

  1. 第一阶段(QPS 100+):MySQL 拆出,Redis 留在应用服务器(减少网络跳转)
  2. 第二阶段(QPS 500+):Redis 升级为哨兵或 Cluster,MySQL 主从分离
  3. 终极方案:容器化(Docker + cgroups 限频)+ Service Mesh(如 Istio)实现细粒度治理

✅ 总结:一句话原则

“宁可浪费 30% 资源,绝不让两个服务在内存、I/O、CPU 上相互踩踏。”
—— 所有配置的核心目标:用确定性的资源边界,换取不确定的业务稳定性。

如需,我可为你生成:

  • 完整的 my.cnf + redis.conf 安全模板(适配 4C8G/8C16G)
  • Prometheus 告警规则 YAML
  • 自动化部署 Ansible Playbook
    欢迎随时提出 👇
未经允许不得转载:云服务器 » 单台云服务器上同时部署MySQL和Redis的最佳实践是什么?