对比Mysql主从分离问题,数据库的主从分离大概可以从两方面考虑

  • A) 数据读不一致问题
    MySQL:采用事务位点标记的方法,在从库中无法读取到未执行的事务中的数据 + 加速同步措施(多线程刷binlog…)
    Redis:主从同步延迟监控机制 + 同步删除 + 加速同步措施(RDB大小限制…)
  • B) 主从切换问题
    MySQL:主从事务同步位点机制
    Redis:哨兵跨服务器访问 + 调整心跳响应上限

以下分析Redis中的主从分离问题

1. 主从不同步—从库读到旧数据

Redis主从是异步复制,无法保证强一致性

  • 解决方法:
    A) 保持主从库间网络通信良好
    B) 开发监控程序监视每个从库与主库之间的延迟程度(从主库的复制积压缓冲区读取两者的同步offset),延迟程度大就暂时断开连接,防止客户端从从库读到旧数据。

2. 从库读到已被主库删除的数据(Redis的惰性删除 + 定期删除 + 定时删除机制)

主库中对一个key设置了过期时间(EXPIRE),但是从库完成该指令的时间慢于主库,所以在从库中该数据删除的时间往后移了

  • 解决方法
    尽量使用某个固定时间点作为key删除的时间(EXPIREAT),那么主从库会同时删除。

ps:

  • 惰性删除:key过期后,Redis不会直接删除该key,而是等客户端下次再访问该key时检查该key的过期时间,发现过期后再删除该key,然后重新从数据库读数据(可以减少删除数据的CPU开销,一般都是同时开启惰性删除、定期删除、定时删除
  • 定时删除:每隔一段时间随机抽取一批keys,检查过期时间,过期了的就删除。

3. 无法进行主从切换

protected-mode被设置为yes,导致哨兵只能被本地服务器的Redis实例访问,如果Redis集群分布在多个服务器,造成哨兵无法通信并进行选主 。

  • 解决方法:
    protected-mode设置为no,然后绑定集群中所有的服务器ip,保证集群通信正常,且可以防止外部ip侵入Redis集群。

4. 主从切换时间超过心跳响应时间上限

主从切换时,Redis实例无法向集群响应心跳,当某个实例心跳响应超时时会被踢出集群,导致该主从实例失效。

  • 解决方法
    合理设置心跳响应时间(cluster-node-timeout

5. 从库内存过小导致数据不一致

从库先到达内存上限,执行内存淘汰机制,导致主从数据不一致。

  • 解决方法
    主从库的内存要差不多。

6. 从库缓存区过小导致全量RDB同步失败

从库全量同步时,接收的RDB文件超出缓冲区上限,导致本次同步失败,再申请下一次同步仍然会失败,导致死循环占用主库大量CPU资源。

  • 解决方法
    主从库都要选择合适的缓冲区大小。