BGP多线主机MySQL性能榨干实录:innodb_flush_method + 内核IO调度 + RPS/RFS三管齐下

1. 为什么BGP多线主机数据库IO容易成为瓶颈

很多人觉得BGP多线主机网络带宽充裕,MySQL慢是SQL写得不好。但实际在高并发场景下,磁盘IO延迟和CPU中断分布不均才是隐形杀手。特别是当服务器同时承担多线接入(电信、联通、移动)、MySQL读写混合、以及日志落盘时,传统ext4 + CFQ调度器会让NVMe SSD的延迟从几十微秒飙到几毫秒。本文以轻云互联BGP多线主机(万兆网卡 + NVMe SSD)为例,从内核层面到MySQL参数,给出可复现的调优方案。

2. 第一步:内核IO调度器选型——抛弃CFQ

现代NVMe SSD的IOPS足够高,CFQ的公平队列反而增加瓶颈。推荐使用none或kyber(Linux 4.14+)。

# 查看当前调度器
cat /sys/block/nvme0n1/queue/scheduler

# 临时改为none
echo none > /sys/block/nvme0n1/queue/scheduler

# 持久化(CentOS/RHEL)
grubby --update-kernel=ALL --args="elevator=none"

# 或者使用udev规则
echo 'ACTION=="add|change", KERNEL=="nvme[0-9]*n[0-9]*", ATTR{queue/scheduler}="none"' > /etc/udev/rules.d/60-iosched.rules

验证:iostat -x 1 观察avgqu-sz < 1,r_await < 0.1ms。

3. 第二步:MySQL的innodb_flush_method——NVMe专用配置

默认innodb_flush_method=fsync会经过系统页缓存,导致双缓冲。NVMe SSD支持原生O_DIRECT,跳过OS Cache,降低抖动。

# my.cnf 示例
[mysqld]
innodb_flush_method = O_DIRECT_NO_FSYNC    # MySQL 5.7+ 推荐,NVMe下性能最佳
innodb_flush_neighbors = 0                 # SSD无需预读相邻页
innodb_io_capacity = 2000                  # 根据实际磁盘IOPS调整
innodb_io_capacity_max = 4000
innodb_buffer_pool_size = 16G             # 物理内存的60%以上
innodb_log_buffer_size = 64M
innodb_log_file_size = 2G

关键解析O_DIRECT_NO_FSYNC 在MySQL 5.7.12后引入,它使用O_DIRECT写数据文件,但跳过fsync(因为NVMe掉电保护足够可靠)。如果数据库业务对持久性要求极高(如金融),可改用O_DIRECT

验证方法:sysbench oltp_write_only --threads=64 run 对比调整前后TPS提升,通常可提升30%~50%。

4. 第三步:网卡多队列 + RPS/RFS——让MySQL处理核不再“一核有难多核围观”

BGP多线主机网卡通常支持多队列(查看lspci -vvv | grep -i MSI-X)。但IRQ默认绑定在CPU0上,导致网络中断和MySQL争抢同一核心。我们需要:

  • 将网卡每个队列的IRQ分别绑定到不同CPU
  • 开启RPS (Receive Packet Steering) 和 RFS (Receive Flow Steering) 平衡软中断
# 假设网卡eth0有8个队列,CPU核心0-7
# 导入irqbalance(可选关闭)
systemctl stop irqbalance

# 查看irq
cat /proc/interrupts | grep eth0

# 手动绑定(示例:将队列0-7绑定到CPU0-7)
for i in {0..7}; do echo $i > /proc/irq/$(awk -v q=$i '/eth0-tx.*-0/ {print $1}' /proc/interrupts | sed 's/://')/smp_affinity_list; done

# 开启RPS/RFS
# 假设CPU掩码为0-7(十六进制0xff)
echo ff > /sys/class/net/eth0/queues/rx-0/rps_cpus
echo ff > /sys/class/net/eth0/queues/tx-0/xps_cpus
echo 4096 > /proc/sys/net/core/rps_sock_flow_entries
echo 4096 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt

验证:mpstat -P ALL 1 观察各核心软中断(%soft)和硬中断(%irq)是否均匀分布。perf top -p $(pidof mysqld) 确认spin_lock等争用减少。

5. 完整压测验证

部署完成后,使用sysbench进行读写混合压测,同时通过netstat -s观察TCP重传率(应<0.1%)。

sysbench /usr/share/sysbench/oltp_read_write.lua --threads=128 --time=300 --mysql-db=test --tables=10 --table-size=1000000 run

预期结果:在轻云互联BGP多线主机(4核8G NVMe)上,调整后TPS从2500提升至4200,P99延迟从50ms降至12ms。

6. 排错备忘

  • 如果开启O_DIRECT后出现InnoDB: Operating system error number 22,确认内核支持O_DIRECT_NO_FSYNC,或回退至O_DIRECT
  • RPS配置后性能反而下降:检查rps_flow_cnt是否太小,增大至8192。
  • 若BGP多线主机有多块网卡(业务+存储),请分别独立绑定IRQ,避免干扰。

以上三要素(内核IO调度、MySQL缓存策略、网络中断绑定)是BGP多线高并发场景中容易被忽略的底牌。配合轻云互联这类采用NVMe SSD的BGP主机,无需魔改硬件即可榨出接近原生性能。