频繁的全量复制
问题一
伴随着系统运行,master的数据会越来越多,一旦master重启,runid发生变化,会导致所有的slave都进行全量复制。
redis内部的调优:
- master内部创建master_replid变量,使用runid相同的策略生成,长度41位,并发送给所有slave。
- 在master关闭时执行命令 shutdown save,进行RDB持久化,将runid与offset保存到RDB文件中。
master中存runid与offset的的值存在变量repl-id
,repl-offset
中,可以通过命令redis-check-rdb [RDB文件]
查看,这个命令不是redis客户端中的命令,在redis使用。 - master重启后,加载RDB文件,恢复数据,将RDB文件中保存的runid、offset加载到内存中,此时,在master客户端执行
info
命令,可以看到在变量master_relp_id
,master_repl_offset
中查看。
作用:
保存本机上次runid,重启后恢复,让slave认为还是之前的master。
问题二
如果遇到网络不好的情况,slave不对外提供服务了,在网络恢复后,slave要同步数据,发现因为缓冲区太小了,offset已经越界了,就会触发全量复制。
解决方法也很简单:加大缓冲区大小。通过配置repl-backlog-size
即可。
缓冲区大小设置多少合适?
- 测算master到slave的重连平均时长second
- 获取master平均每秒产生写命令的数据总量write_size_per_second
- 最优复制缓冲区大小 = 2 * second * write_size_per_second
频繁的网络中断
问题一
问题现象
- master的CPU占用过高 或 slave频繁断开连接
问题原因
- slave每秒发送一次
replconf ack
到master - 当slave接到了慢查询(keys *,hgetall等),会占用大量CPU,导致不能在既定的时间给master发信息
- master每秒调用复制定时函数replicationCron(),对比slave发现长时间没有进行响应
结果
- master各种资源(输出缓冲区、带宽、连接)等被严重占用
解决方案
- 设置合理的超时时间,确认是否释放slave,配置:
repl-timeout
,默认60s,超过该时间就释放slave
问题二
问题现象
- slave与master断开连接
问题原因
- master发送ping指令频度低
- master设置的超时时间短
- ping指令在网络中可能丢包
解决方案
- 提高ping指令发送频度,配置:
repl-ping-slave-period
。超时时间至少是ping指令频度的5-10倍,不然slave很容易被判定为超时。
数据不一致
问题现象
- 多个slave数据不同步
问题原因
- 网络信息不同步,数据发送有延迟
解决方案
- 优化主从空间的网络环境,通常放在同一机房部署,如果使用云服务器的话就要注意这个现象。
- 监控主从节点延迟(通过offset)判断,如果slave延迟过大,可以暂时屏蔽该程序对该slave的数据访问。可以通过
slave-serve-stale-data yes|no
,开启后仅响应info
、slaveof
等少数命令。