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

在单台云服务器上同时部署 MySQL 和 Redis(即“共存部署”)虽常见于开发、测试或轻量级生产场景(如中小流量 Web 应用、内部工具),但需谨慎权衡资源竞争与稳定性风险。这不是高可用/高性能生产环境的推荐架构,但若必须共存,以下是经过验证的最佳实践:


✅ 一、核心原则(先决条件)

  1. 明确适用场景:仅限于 QPS < 500、并发连接 < 200、数据量 < 50GB 的轻量级业务(如博客、后台管理系统、小型 SaaS 试用环境)。
  2. 绝不用于关键生产系统:MySQL(持久化+事务)与 Redis(内存+高吞吐)资源模型冲突显著,共存易引发雪崩(如 Redis 内存耗尽触发 OOM Killer 杀死 MySQL)。
  3. 必须监控告警先行:无监控=裸奔,部署前确保已配置基础指标采集与阈值告警。

✅ 二、资源隔离与分配(最关键!)

资源类型 MySQL 建议分配 Redis 建议分配 说明
CPU 绑定 2~4 核(numactl --cpunodebind=0 --membind=0 mysqld 绑定剩余 1~2 核(taskset -c 4-5 redis-server 避免 CPU 抢占;Redis 单线程,无需多核,但需独占避免调度延迟
内存 innodb_buffer_pool_size = 总内存 × 50%~60%(例:16GB → 8~10GB) maxmemory = 总内存 × 20%~30%(例:16GB → 3~4GB),必须设置 maxmemory-policy(推荐 allkeys-lru ⚠️ 禁止 Redis 使用 swap!echo 'vm.swappiness = 1' >> /etc/sysctl.conf && sysctl -p;MySQL 的 buffer pool 是性能生命线
磁盘 I/O MySQL 数据目录挂载 独立 SSD 分区(如 /data/mysql),启用 innodb_flush_method=O_DIRECT Redis 持久化(RDB/AOF)目录挂载 同一 SSD 但不同分区(如 /data/redis),禁用 AOF 或设为 appendfsync everysec 避免 I/O 争抢;禁止将 Redis RDB/AOF 与 MySQL 放在同一慢速磁盘(如系统盘)
网络端口 MySQL: 3306(建议改非标端口如 3307 并限制 bind-address=127.0.0.1) | Redis:6379(同理改6380bind 127.0.0.1`) 防止外部直接访问,减少攻击面

🔍 验证命令

# 查看内存实际占用(排除缓存干扰)
free -h && cat /proc/meminfo | grep -E "MemAvailable|Buffers|Cached"
# 检查 Redis 是否使用 swap
redis-cli info memory | grep mem_allocator  # 应为 jemalloc

✅ 三、配置优化(针对性调优)

▶ MySQL 关键配置(my.cnf

[mysqld]
# 内存安全边界(防止OOM)
innodb_buffer_pool_size = 8G          # 严格 ≤ 可用内存 × 0.6
innodb_log_file_size = 256M           # 日志大小适中,避免频繁刷盘
innodb_flush_method = O_DIRECT        # 绕过 OS 缓存,减少双写开销
max_connections = 200                 # 严控连接数,避免内存爆炸
wait_timeout = 60                     # 快速回收空闲连接
skip_name_resolve = ON                # 禁用 DNS 解析,提速连接

▶ Redis 关键配置(redis.conf

# 内存与持久化
maxmemory 3gb
maxmemory-policy allkeys-lru
save 900 1     # 降低 RDB 触发频率(默认 900s/1次 → 可放宽至 3600s)
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes      # RDB 失败时拒绝写入,避免数据丢失
rdbcompression yes
rdbchecksum yes
# 禁用 AOF(除非强一致性要求)或设为 everysec
appendonly no                        # 或 appendonly yes + appendfsync everysec
# 安全与资源
bind 127.0.0.1
protected-mode yes
tcp-keepalive 300
# 内存优化(重要!)
activerehashing yes
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes

💡 为什么禁用 AOF?
AOF 重写(BGREWRITEAOF)会 fork 进程,与 MySQL 的 InnoDB 后台线程竞争内存和 CPU,极易触发 OOM。RDB 更轻量,且配合 maxmemory-policy 已满足多数缓存场景。


✅ 四、进程与系统级防护

措施 命令/配置 目的
OOM 优先级控制 echo -1000 > /proc/$(pgrep mysqld)/oom_score_adj
echo -800 > /proc/$(pgrep redis-server)/oom_score_adj
降低 MySQL 被 OOM Killer 杀死的概率(数值越小越不易被杀)
CPU 亲和性绑定 systemd 服务文件中添加:
CPUAffinity=0-3(MySQL)
CPUAffinity=4-5(Redis)
避免跨 NUMA 节点访问内存,提升性能稳定性
I/O 调度器优化 echo deadline > /sys/block/vda/queue/scheduler(SSD) SSD 场景下 deadlinecfq 更低延迟
禁用 Transparent Huge Pages (THP) echo never > /sys/kernel/mm/transparent_hugepage/enabled THP 导致 Redis 内存分配延迟飙升,MySQL 也会受影响

✅ 五、监控与告警(必须落地)

指标 告警阈值 工具建议
内存使用率 > 85%(总内存) node_exporter + Prometheus + Alertmanager
Redis 内存使用率 > 90% of maxmemory redis_exporter
MySQL 连接数 > 90% of max_connections mysqld_exporter
磁盘 I/O Wait > 20%(iowait node_exporter
Redis 拒绝连接数 rejected_connections > 0 redis-cli info stats
MySQL Slow Queries > 5/sec 开启 slow log + pt-query-digest 分析

🚨 立即响应项

  • Redis evicted_keys > 0 → 立即扩容或优化缓存策略
  • MySQL Threads_created > 10/sec → 检查连接池配置(应用层未复用连接)

✅ 六、替代方案建议(强烈推荐演进路径)

场景 推荐方案 优势
开发/测试环境 Docker Compose 隔离 + --memory=4g --cpus=2 限制 快速启停,资源硬隔离
轻量生产(预算有限) 云厂商托管服务(如阿里云 RDS MySQL + 云数据库 Redis) 免运维、自动备份、故障转移、按量付费
中高流量生产 物理分离:MySQL 独占 1 台(8C16G+SSD),Redis 独占 1 台(4C8G+大内存) 彻底消除资源争抢,支持横向扩展
成本敏感但需弹性 Kubernetes + StatefulSet:MySQL 主从 + Redis Cluster 利用 K8s 资源配额(resources.limits)和拓扑感知调度

❌ 绝对禁止的操作(血泪教训)

  • ❌ 不设置 maxmemory → Redis 吃光内存导致 MySQL 被 OOM Kill
  • ❌ 将 MySQL 和 Redis 数据目录放在系统盘(/)→ 磁盘满导致系统崩溃
  • ❌ 开启 Redis AOF + always 同步 → I/O 瓶颈拖垮 MySQL
  • ❌ 使用 swap 交换分区 → Redis 内存页换入换出造成毫秒级延迟突增
  • ❌ 不限制 MySQL max_connections → 小程序连接泄漏即可压垮服务器

✅ 总结:一张检查清单

项目 是否完成 备注
☐ 内存严格分配(MySQL 60% + Redis 30% + 系统 10%) free -h 验证可用内存
☐ CPU 亲和性绑定(taskset / systemd CPUAffinity top -H -p $(pgrep redis) 查看线程 CPU
☐ Redis maxmemory + allkeys-lru 已配置 redis-cli config get maxmemory
☐ MySQL innodb_buffer_pool_size ≤ 可用内存×0.6 mysql -e "show variables like 'innodb_buffer_pool_size'"
☐ 禁用 THP & swappiness=1 cat /sys/kernel/mm/transparent_hugepage/enabled
☐ 所有服务 bind 127.0.0.1,关闭公网访问 ss -tlnp | grep -E "(3306|6379)"
☐ 部署 Prometheus + Grafana 基础监控 至少包含内存、CPU、连接数、Redis evictions

最后忠告:共存部署是技术债务。上线后第一件事——规划迁移至分离架构。每多运行一天,故障风险指数级增长。

如需,我可提供:
🔹 完整的 systemd 服务配置模板(含资源限制)
🔹 Docker Compose 示例(带内存/CPU 限制)
🔹 Prometheus 告警规则 YAML
欢迎随时提出具体需求!

未经允许不得转载:云知识CLOUD » 单台云服务器上同时部署MySQL和Redis的最佳实践是什么?