在高并发场景下,Redis 与 MySQL 的架构性能瓶颈往往不仅出现在应用层或数据库配置层面,操作系统内核参数的调优同样至关重要。如果 OS 层面的资源限制(如文件句柄、内存管理、网络栈等)未优化,即使 Redis 和 MySQL 配置再完美,系统也会因底层资源耗尽而崩溃或性能骤降。
以下是针对高并发场景下,Redis + MySQL 架构需要重点关注的操作系统级调优方向:
1. 文件描述符(File Descriptors)调优
在高并发连接数下,每个 TCP 连接都需要占用一个文件描述符。默认值通常仅为 1024,极易成为瓶颈。
- 用户级限制 (
ulimit):- 确保运行 Redis 和 MySQL 的用户(通常是
redis和mysql)拥有足够的最大打开文件数。 - 修改
/etc/security/limits.conf:redis soft nofile 65535 redis hard nofile 65535 mysql soft nofile 65535 mysql hard nofile 65535
- 确保运行 Redis 和 MySQL 的用户(通常是
- 系统级限制 (
/proc/sys/fs/file-max):- 设置系统全局允许的最大文件句柄总数,防止被其他进程抢占导致服务不可用。
- 命令:
echo 1000000 > /proc/sys/fs/file-max(建议根据内存大小调整,例如每 GB 内存对应 20k-50k 句柄)。 - 持久化配置在
/etc/sysctl.conf中:fs.file-max = 1000000。
2. 网络栈(Network Stack)调优
高并发意味着大量的 TCP 连接建立、断开和数据包处理,Linux 默认的网络参数是为低延迟或小规模设计的,需针对性优化。
- TCP 端口范围扩展:
- 高并发下,客户端可能发起大量短连接,导致本地临时端口耗尽。
- 配置
/etc/sysctl.conf:net.ipv4.ip_local_port_range = 1024 65535
- TIME_WAIT 状态处理:
- 高并发写操作或频繁断连会导致大量 socket 处于
TIME_WAIT状态,占用端口。 - 开启复用并缩短等待时间:
net.ipv4.tcp_tw_reuse = 1 # 允许重用 TIME_WAIT sockets net.ipv4.tcp_fin_timeout = 30 # 缩短 FIN-WAIT-2 超时时间 net.core.somaxconn = 65535 # 增加监听队列长度(关键,防止 SYN 攻击或积压) net.ipv4.tcp_max_syn_backlog = 8192 # SYN 队列长度
- 高并发写操作或频繁断连会导致大量 socket 处于
- TCP 缓冲区优化:
- 增大接收/发送缓冲区,减少上下文切换,提高吞吐量。
net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 net.ipv4.tcp_rmem = 4096 87380 16777216 net.ipv4.tcp_wmem = 4096 65536 16777216
- 增大接收/发送缓冲区,减少上下文切换,提高吞吐量。
- 禁用 Nagle 算法:
- Redis 和 MySQL 对实时性要求高,应关闭 Nagle 算法以减少小包延迟。
net.ipv4.tcp_no_metrics_save = 1 net.ipv4.tcp_moderate_rcvbuf = 0
- Redis 和 MySQL 对实时性要求高,应关闭 Nagle 算法以减少小包延迟。
3. 内存管理(Memory Management)
Redis 是纯内存数据库,MySQL 也是重度依赖内存的组件,OS 的内存回收机制直接影响性能。
- 关闭透明大页(Transparent Huge Pages, THP):
- THP 虽然能提升顺序读写性能,但会导致 Redis 和 MySQL 出现严重的内存碎片和抖动(Latency Spikes)。必须关闭。
- 临时关闭:
echo never > /sys/kernel/mm/transparent_hugepage/enabled - 永久关闭:在
/etc/default/grub中添加transparent_hugepage=never并更新 grub。
- 调整 Swappiness:
- Redis 和 MySQL 不应使用 Swap,否则会导致严重卡顿。
- 将 swappiness 设为极低值(0 或 1),强制优先使用物理内存。
vm.swappiness = 1
- NUMA 调优:
- 如果是多路服务器,确保 Redis/MySQL 进程绑定到特定的 CPU 核和 NUMA 节点,避免跨节点访问内存带来的延迟。
- 可使用
numactl --interleave=all启动服务,或手动绑定 CPU 亲和性。
4. 中断与 CPU 调度
高并发下,网卡中断会消耗大量 CPU 周期,导致业务线程无法及时获取 CPU 时间片。
- IRQ 均衡(Interrupt Affinity):
- 将网卡的中断请求分散到多个 CPU 核心上,避免单核过载。
- 工具:
irqbalance服务通常已自动处理,但在极端高并发下,建议手动将 Redis/MySQL 绑定的 CPU 核排除在中断处理之外,或将特定网卡中断绑定到空闲核。
- CPU 频率调节:
- 将 CPU 模式设置为
performance,禁止动态降频(Governor),保证计算能力稳定。echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
- 将 CPU 模式设置为
- CFS 调度优化:
- 对于 Redis 这种对延迟极其敏感的服务,可适当调整 CFS 的虚拟时钟精度,但这通常属于高级调优,一般保持默认即可,重点在于隔离。
5. 磁盘 I/O 调优
MySQL 涉及大量随机读写的磁盘操作,而 Redis 若开启 AOF/RDB 持久化也会产生 IO。
- I/O 调度器选择:
- 对于 SSD/NVMe,建议使用
none或mq-deadline;对于机械硬盘,建议使用deadline或bfq。 - 查看当前:
cat /sys/block/sda/queue/scheduler - 修改:
echo mq-deadline > /sys/block/sda/queue/scheduler
- 对于 SSD/NVMe,建议使用
- 写入缓存策略:
- 对于 MySQL 的数据盘,通常希望减少刷盘延迟,可以调整
vm.dirty_ratio和vm.dirty_background_ratio,让内核积攒更多数据后再批量写入磁盘(需配合 RAID 卡电池或 NVMe 缓存,否则有掉电风险)。 - 对于 Redis 的 RDB/AOF,建议单独挂载 SSD 并开启
noatime选项。
- 对于 MySQL 的数据盘,通常希望减少刷盘延迟,可以调整
6. 安全与隔离
- SELinux/AppArmor:
- 在生产环境中,如果配置不当,SELinux 可能会拦截 Redis 或 MySQL 的文件访问或网络绑定,导致异常。建议在调试阶段将其设置为
Permissive或Disabled,生产环境则需精细配置策略。
- 在生产环境中,如果配置不当,SELinux 可能会拦截 Redis 或 MySQL 的文件访问或网络绑定,导致异常。建议在调试阶段将其设置为
- 容器化部署(Docker/K8s):
- 如果使用容器,务必在启动时传递
--ulimit nofile=65535:65535和--cap-add SYS_ADMIN(如需调整内核参数),并限制 CPU 和内存配额,防止邻居干扰。
- 如果使用容器,务必在启动时传递
总结与验证建议
在进行上述调优后,不要盲目重启服务,建议按以下步骤验证:
- 压力测试:使用
sysbench、redis-benchmark或wrk进行压测,观察 QPS、P99 延迟和错误率的变化。 - 监控指标:关注
netstat -an | grep TIME_WAIT、dmesg中的 OOM Killer 日志、vmstat的si/so(Swap 交换情况)以及sar -n DEV的网络丢包率。 - 灰度上线:先在非核心时段或从节点生效,确认无误后再全量推送到主节点。
核心原则:高并发下的 OS 调优本质是消除资源争抢和减少上下文切换。对于 Redis+MySQL 架构,关闭 THP、扩大文件句柄、优化 TCP 参数以及禁止 Swap是最基础且收益最高的四步操作。
轻量云Cloud