在单台云服务器上同时部署 MySQL 和 Redis 是常见但需谨慎的操作。虽然适用于开发、测试或轻量级生产场景(如小型网站、内部工具),但不推荐用于中高负载或关键业务的生产环境。以下是兼顾稳定性、性能与安全性的最佳实践总结:
✅ 一、前提判断:是否真的需要共存?
| 场景 | 建议 |
|---|---|
| 开发/测试/POC | ✅ 可接受,需合理隔离和资源限制 |
| 日活 < 1k、QPS < 50 的小应用(如企业内网系统) | ⚠️ 可行,但必须严格调优和监控 |
| 高并发、核心交易、数据强一致性要求场景 | ❌ 强烈建议分离部署(物理/逻辑隔离) |
💡 关键风险:资源争抢(CPU/内存/IO)、故障耦合(一个服务崩溃可能拖垮另一个)、安全纵深不足、备份恢复复杂化。
✅ 二、核心最佳实践(按优先级排序)
1. 资源隔离与限制(最重要!)
- 内存分配(避免 OOM):
- MySQL:
innodb_buffer_pool_size设为 物理内存的 50–60%(例:16GB 内存 → 设为 8–9GB)。 - Redis:通过
maxmemory硬限制(如maxmemory 3gb),并设置maxmemory-policy allkeys-lru或volatile-lru。 - ✅ 预留至少 2–3GB 给 OS + 其他进程(如 SSH、监控 agent)。
- MySQL:
- CPU 控制:
- 使用
systemd或cgroups v2限制 CPU 配额(尤其 Redis 单线程易占满 1 核):# 示例:限制 Redis 最多使用 1 个逻辑 CPU(50% 的 2 核机器) sudo systemctl set-property redis.service CPUQuota=50%
- 使用
- 磁盘 IO 分离(强烈推荐):
- MySQL 数据目录(
/var/lib/mysql)与 Redis 持久化目录(/var/lib/redis)分挂载点(如/data/mysql,/data/redis)。 - 若为云盘,确保使用 SSD 类型(如 AWS gp3 / 阿里云 ESSD),避免共享磁盘队列争抢。
- MySQL 数据目录(
2. 端口与网络加固
- 修改默认端口(降低扫描攻击面):
- MySQL:
port = 3307(而非 3306) - Redis:
port = 6380(而非 6379),且bind 127.0.0.1(禁止监听 0.0.0.0!)
- MySQL:
- 启用防火墙(
ufw/firewalld):ufw allow from 127.0.0.1 to any port 3307 # 仅本地 MySQL 访问 ufw allow from 127.0.0.1 to any port 6380 # 仅本地 Redis 访问 ufw deny 6379 3306 # 封禁默认端口
3. 安全配置(防未授权访问)
- MySQL:
- 删除匿名用户、
test数据库; - 创建专用应用用户(非
root),限制HOST为127.0.0.1; - 启用
validate_password插件,强制强密码。
- 删除匿名用户、
- Redis:
- 必须设置密码:
requirepass your_strong_password_here(避免空密码!); - 禁用危险命令(如
FLUSHDB,CONFIG,EVAL):rename-command FLUSHDB "" rename-command CONFIG "" rename-command EVAL "" - 启用
protected-mode yes(默认开启,确保 bind+密码生效)。
- 必须设置密码:
4. 持久化与备份策略
- MySQL:
- 开启
binlog(log-bin = /var/lib/mysql/mysql-bin)用于增量恢复; - 定期
mysqldump或使用mydumper(更高效),结合cron+rclone同步到对象存储(如 OSS/S3)。
- 开启
- Redis:
- 生产环境禁用 RDB 单一快照(可能阻塞)→ 改用 AOF +
appendfsync everysec; - 设置
auto-aof-rewrite-percentage 100&auto-aof-rewrite-min-size 64mb; - AOF 文件同样需定期备份(注意文件权限)。
- 生产环境禁用 RDB 单一快照(可能阻塞)→ 改用 AOF +
5. 监控与告警(不可省略)
- 必须监控指标:
| 服务 | 关键指标 | 工具建议 |
|——–|———–|————|
| MySQL |Threads_connected,Innodb_buffer_pool_hit_ratio,Slow_queries,Seconds_behind_master(若主从) |mysqld_exporter+ Prometheus + Grafana |
| Redis |used_memory,mem_fragmentation_ratio,connected_clients,evicted_keys,rejected_connections|redis_exporter|
| 系统 |load average,free memory,disk I/O wait,swap usage|node_exporter| - 设置告警阈值(示例):
- 内存使用率 > 90% → 触发告警;
- Redis
evicted_keys > 0→ 表明内存不足,需扩容或优化; - MySQL
Threads_connected持续 >max_connections * 0.8→ 连接池泄漏风险。
6. 部署与运维规范
- 使用 官方包或容器化(推荐 Docker,但需注意资源限制):
# docker-compose.yml(示例) services: mysql: image: mysql:8.0 mem_limit: 9g cpus: 2.0 environment: MYSQL_ROOT_PASSWORD: secure_pass volumes: - /data/mysql:/var/lib/mysql redis: image: redis:7-alpine mem_limit: 3g cpus: 0.5 command: redis-server /usr/local/etc/redis.conf volumes: - /data/redis:/data - ./redis.conf:/usr/local/etc/redis.conf - 禁止 root 用户运行服务:MySQL/Redis 均以专用低权限用户(如
mysql,redis)启动。 - 日志统一管理:重定向到
journald或rsyslog,设置 logrotate 防止磁盘打满。
❌ 三、绝对避免的错误做法
- ✖️ 不设
maxmemory或innodb_buffer_pool_size→ OOM Killer 杀进程; - ✖️ Redis 绑定
0.0.0.0且无密码 → 全网可未授权访问(勒索病毒高危!); - ✖️ MySQL 和 Redis 共享同一块机械硬盘(HDD)→ IO 彻底瓶颈;
- ✖️ 使用
sudo service mysql start等方式手动启停 → 无法保证资源控制; - ✖️ 忽略 swap:云服务器建议 关闭 swap(
sudo swapoff -a && sudo sysctl vm.swappiness=0),避免内存压力下性能雪崩。
📈 四、性能调优速查表(16GB 内存服务器示例)
| 参数 | MySQL 推荐值 | Redis 推荐值 | 说明 |
|---|---|---|---|
| 内存占用 | innodb_buffer_pool_size = 8G |
maxmemory 3G |
预留 3G 给 OS + 缓存 |
| 最大连接数 | max_connections = 200 |
maxclients 1000 |
根据应用连接池调整 |
| 日志刷盘 | innodb_flush_log_at_trx_commit = 1(强一致性)sync_binlog = 1 |
appendfsync everysec |
平衡安全性与性能 |
| 网络 | skip-networking = OFFbind-address = 127.0.0.1 |
bind 127.0.0.1protected-mode yes |
仅本地通信 |
✅ 总结:一句话原则
“宁可资源冗余,不可争抢失控;宁可部署分离,不可安全妥协。”
若业务增长,应优先将 MySQL/Redis 迁移至独立实例(甚至读写分离/分片),而非在单机上堆砌参数。
如需,我可提供:
- 完整的
my.cnf和redis.conf安全模板(含注释); - Prometheus 监控告警规则 YAML;
- 自动化部署脚本(Bash/Docker Compose);
- 故障排查清单(如 Redis 内存暴涨、MySQL 连接数耗尽等)。
欢迎随时提出具体场景(如“阿里云 4C8G 部署 WordPress”),我可给出定制化方案。
CDNK博客