Redis主从复制时,如何大Key以减轻同步带宽压力?
- 内容介绍
- 文章标签
- 相关推荐
本文共计906个文字,预计阅读时间需要4分钟。
在Redis主从复制过程中,如果某个key是大Key(例如,数MB乃至数十MB的hash、zset或list),主节点会将整个key序列化后,通过REPLCONF协议一次性发送给从节点。这不仅会占用大量带宽,还可能阻塞其他命令的复制,导致从节点上的master_repl_offset严重滞后,甚至可能因timeout导致连接断开。
典型现象包括:INFO replication中slave_repl_offset长期停滞、net_output_bytes突增、从节点日志频繁出现Timeout waiting for bulk read。
- Redis 6.0+ 虽支持
repl-diskless-sync yes减少磁盘IO,但不解决大Key单次传输问题 -
client-output-buffer-limit slave默认值(256MB/64MB/60s)很容易被一个大Key打穿,直接断连 - 主节点
redis-cli --bigkeys能发现大Key,但不会告诉你它正在拖垮复制
用HSCAN/SSCAN等渐进式命令拆分大hash/set
不能直接HDEL或DEL大Key——这会造成主节点瞬间高CPU和阻塞,且删除操作本身又会作为一条大命令同步到从节点,形成二次冲击。
正确做法是:在业务低峰期,用游标方式分批读取+写入新结构,再逐步清理旧Key。
- 对大
hash:用HSCAN myhash 0 COUNT 100每次拉100个field,写入myhash:shard001等新Key,再HDEL原field - 对大
set:用SSCAN myset 0 COUNT 500,写入myset:part1~myset:partN,最后SREM原成员 - 务必在主节点执行,确保所有操作都进入AOF和复制流;从节点只读,不参与拆分逻辑
- 拆分脚本里加
SLEEP 0.01(如用redis-cli --eval配合Lua)避免压垮主节点
避免LRU/LFU驱逐加剧大Key问题
当内存紧张触发淘汰时,Redis默认按volatile-lru或allkeys-lfu策略选Key。若大Key恰好被选中,DEL它会产生巨量释放事件,同步到从节点又是一次带宽洪峰。
- 配置
maxmemory-policy noeviction可规避,但需确保业务有兜底内存控制 - 更稳妥的是:用
MEMORY USAGE bigkey定期扫描,结合OBJECT FREQ和OBJECT IDLETIME判断是否真冷数据,再人工介入拆分 - 禁止用
CONFIG SET maxmemory-policy在线切换策略——该命令会阻塞主线程,且切换瞬间可能批量淘汰
监控必须覆盖bigkey + replication lag双维度
只看lag指标(如slave_repl_offset - master_repl_offset)不够,因为滞后可能由网络抖动引起;只看bigkey也不行,因为不是所有大Key都会实时影响复制。
- 每10分钟跑一次
redis-cli -h $host -p $port --bigkeys -i 0.01(-i降低采样干扰),结果存入TSDB - 告警规则要联动:当
bigkey_size > 1MB**且**replication_lag > 5000ms同时成立才触发 - 从节点
INFO commandstats中关注cmdstat_hscan调用量突增,可能是拆分任务在运行,需确认是否已收敛
真正麻烦的从来不是发现大Key,而是拆分过程中新老Key并存带来的业务一致性风险——比如读请求还在查旧hash,而写请求已开始更新新shard。这部分必须靠业务层双写+灰度开关控制,Redis本身不提供原子跨Key迁移能力。
本文共计906个文字,预计阅读时间需要4分钟。
在Redis主从复制过程中,如果某个key是大Key(例如,数MB乃至数十MB的hash、zset或list),主节点会将整个key序列化后,通过REPLCONF协议一次性发送给从节点。这不仅会占用大量带宽,还可能阻塞其他命令的复制,导致从节点上的master_repl_offset严重滞后,甚至可能因timeout导致连接断开。
典型现象包括:INFO replication中slave_repl_offset长期停滞、net_output_bytes突增、从节点日志频繁出现Timeout waiting for bulk read。
- Redis 6.0+ 虽支持
repl-diskless-sync yes减少磁盘IO,但不解决大Key单次传输问题 -
client-output-buffer-limit slave默认值(256MB/64MB/60s)很容易被一个大Key打穿,直接断连 - 主节点
redis-cli --bigkeys能发现大Key,但不会告诉你它正在拖垮复制
用HSCAN/SSCAN等渐进式命令拆分大hash/set
不能直接HDEL或DEL大Key——这会造成主节点瞬间高CPU和阻塞,且删除操作本身又会作为一条大命令同步到从节点,形成二次冲击。
正确做法是:在业务低峰期,用游标方式分批读取+写入新结构,再逐步清理旧Key。
- 对大
hash:用HSCAN myhash 0 COUNT 100每次拉100个field,写入myhash:shard001等新Key,再HDEL原field - 对大
set:用SSCAN myset 0 COUNT 500,写入myset:part1~myset:partN,最后SREM原成员 - 务必在主节点执行,确保所有操作都进入AOF和复制流;从节点只读,不参与拆分逻辑
- 拆分脚本里加
SLEEP 0.01(如用redis-cli --eval配合Lua)避免压垮主节点
避免LRU/LFU驱逐加剧大Key问题
当内存紧张触发淘汰时,Redis默认按volatile-lru或allkeys-lfu策略选Key。若大Key恰好被选中,DEL它会产生巨量释放事件,同步到从节点又是一次带宽洪峰。
- 配置
maxmemory-policy noeviction可规避,但需确保业务有兜底内存控制 - 更稳妥的是:用
MEMORY USAGE bigkey定期扫描,结合OBJECT FREQ和OBJECT IDLETIME判断是否真冷数据,再人工介入拆分 - 禁止用
CONFIG SET maxmemory-policy在线切换策略——该命令会阻塞主线程,且切换瞬间可能批量淘汰
监控必须覆盖bigkey + replication lag双维度
只看lag指标(如slave_repl_offset - master_repl_offset)不够,因为滞后可能由网络抖动引起;只看bigkey也不行,因为不是所有大Key都会实时影响复制。
- 每10分钟跑一次
redis-cli -h $host -p $port --bigkeys -i 0.01(-i降低采样干扰),结果存入TSDB - 告警规则要联动:当
bigkey_size > 1MB**且**replication_lag > 5000ms同时成立才触发 - 从节点
INFO commandstats中关注cmdstat_hscan调用量突增,可能是拆分任务在运行,需确认是否已收敛
真正麻烦的从来不是发现大Key,而是拆分过程中新老Key并存带来的业务一致性风险——比如读请求还在查旧hash,而写请求已开始更新新shard。这部分必须靠业务层双写+灰度开关控制,Redis本身不提供原子跨Key迁移能力。

