问题出现得很突然,日志倒是留得挺全。腾讯云 4 核 8G 上跑 Redis 6.2,开了 AOF,为了不丢数据把 appendfsync 从 everysec 改成 always,之后订单接口 p99 从 2ms 涨到 35ms,iostat 上写 IOPS 翻了十倍,磁盘还是普通云盘。
刚开始盯着「AOF 重写期间子进程和主进程抢同一块盘,fsync 延迟被进一步放大」,折腾了半个多小时,排掉了。
把日志和配置对完,能解释这个现象的基本就这几处。每条写命令都要等一次 fsync 返回,网络与磁盘的往返直接加在每次写入上。还有一种是普通云盘单次 fsync 本身有毫秒级抖动,高峰期排队更明显。
不容易想到的是,磁盘写缓存被关,操作系统层面也省不掉这一次落盘。
先看延迟是刷盘造成的还是命令变多
redis-cli info persistence | grep -E 'aof_delayed_fsync|aof_last_write_status'
再往下改回每秒刷盘,并让重写期间不刷盘
redis-cli config set appendfsync everysec && redis-cli config set no-appendfsync-on-rewrite yes
随后确认磁盘的真实写延迟
iostat -xdm 1 3 | grep -E 'Device|vda'
等前面都确认过,再核对重写是否被频繁触发
redis-cli info persistence | grep -E 'aof_rewrite_in_progress|aof_base_size|aof_current_size'
改完先别撤,确认这几项。aof_delayed_fsync 不再增长,接口 p99 回落到 5ms 以内,iostat 的写 IOPS 回到原来的量级,aof_last_write_status 显示 ok。
提醒一点。不丢数据要靠主从加落盘组合,单靠 always 换不来零丢失,只是把延迟从系统层挪到每次请求上。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。
