对比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资源。
- 解决方法
主从库都要选择合适的缓冲区大小。