如果master还没有同步到slave业务读取脏数据问题
问题阐述:master用来写,slave用来读,当master还没有同步到slave这时候我们读slave出现了脏数据
解决方案:在redis缓存中增加标记
.A发起写请求,更新了主库,但在缓存中设置一个标记,代表此数据已经更新,标记格式(业务代号:数据库:表:主键ID)根据自己业务场景。
2.设置此标记,要加上过期时间,可以为预估的主库和从库同步延迟的时间.
3.B发起读请求的时候,先判断此请求的业务在缓存中有没有更新标记
4.如果存在标记,走主库;如果没有走从库。
下面是redis自身的丢失问题(系统级)
1、异步复制导致数据丢失:因为master -> slave的复制是异步的,当master还没有把数据复制到slave的时候宕机了,此时这些部分数据就丢失了
2、脑裂导致数据丢失:master犹豫某种原因失去网络连接了,这时候哨兵会检测出当前主从没有master了就会在slave中找到一个设置成master,这时候原来的master还没有死,就出现了两个master,然后第一个master网络有好用了,在这个期间不断地向新的master写入数据,然后哨兵检测到老的master还活着,会将新的master再次编程slave,然后重新进行主从复制,这时候会造成数据丢失。
解决方案
如何解决异步复制:配置两个属性
min-slaves-to-write 1
min-slaves-max-lag 10
要求至少有1个slave,数据复制和同步的延迟不能超过10秒
如果说一旦所有的slave,数据复制和同步的延迟都超过了10秒钟,那么这个时候,master就不会再接收任何请求了
(1)减少异步复制的数据丢失
有了min-slaves-max-lag这个配置,就可以确保说,一旦slave复制数据和ack延时太长,就认为可能master宕机后损失的数据太多了,那么就拒绝写请求,这样可以把master宕机时由于部分数据未同步到slave导致的数据丢失降低的可控范围内
(2)减少脑裂的数据丢失
如果一个master出现了脑裂,跟其他slave丢了连接,那么上面两个配置可以确保说,如果不能继续给指定数量的slave发送数据,而且slave超过10秒没有给自己ack消息,那么就直接拒绝客户端的写请求
这样脑裂后的旧master就不会接受client的新数据,也就避免了数据丢失