Redis 核心技术与实战
蒋德钧
中科院计算所副研究员
81696 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 53 讲
开篇词 (1讲)
实践篇 (28讲)
Redis 核心技术与实战
15
15
1.0x
00:00/00:00
登录|注册

33 | 脑裂:一次奇怪的数据丢失

每课一问
小结
如何应对脑裂问题?
为什么脑裂会导致数据丢失?
为什么会发生脑裂?
脑裂问题分析与解决

该思维导图由 AI 生成,仅供参考

你好,我是蒋德钧。
在使用主从集群时,我曾遇到过这样一个问题:我们的主从集群有 1 个主库、5 个从库和 3 个哨兵实例,在使用的过程中,我们发现客户端发送的一些数据丢失了,这直接影响到了业务层的数据可靠性。
通过一系列的问题排查,我们才知道,这其实是主从集群中的脑裂问题导致的。
所谓的脑裂,就是指在主从集群中,同时有两个主节点,它们都能接收写请求。而脑裂最直接的影响,就是客户端不知道应该往哪个主节点写入数据,结果就是不同的客户端会往不同的主节点上写入数据。而且,严重的话,脑裂会进一步导致数据丢失。
那么,主从集群中为什么会发生脑裂?脑裂为什么又会导致数据丢失呢?我们该如何避免脑裂的发生呢?这节课,我就结合我遇见的这个真实问题,带你一起分析和定位问题,帮助你掌握脑裂的成因、后果和应对方法。

为什么会发生脑裂?

刚才我提到,我最初发现的问题是,在主从集群中,客户端发送的数据丢失了。所以,我们首先要弄明白,为什么数据会丢失?是不是数据同步出了问题?

第一步:确认是不是数据同步出现了问题

在主从集群中发生数据丢失,最常见的原因就是主库的数据还没有同步到从库,结果主库发生了故障,等从库升级为主库后,未同步的数据就丢失了。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文介绍了主从集群中可能出现的脑裂问题,并提出了相应的解决策略。脑裂是指在主从集群中同时存在两个主库能够接收写请求,可能导致数据丢失。文章首先解释了脑裂的概念和影响,然后详细分析了脑裂发生的原因和导致数据丢失的过程。作者提出了通过合理配置参数min-slaves-to-write和min-slaves-max-lag来预防脑裂的发生,并给出了具体的配置建议。此外,文章还通过案例分析和问题提问的方式帮助读者更好地理解和应对脑裂问题。通过本文,读者可以深入了解脑裂问题的成因、后果和解决方法,为实际应用中的主从集群部署提供了有益的参考。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Redis 核心技术与实战》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(26)

  • 最新
  • 精选
  • 小文同学
    穿插使用 CAP 理论来分析一下课程的内容: 1. redis 集群允许脑裂存在,其实是一种可用性高的特征,但不保证数据一直。 2. redis 通过设置两个参数,一定程度上其实是在降低可用性,以提供数据一致性。 3. 为什么愿意降低可用性?因为那部分的数据会因为主从切换而丢失,所以宁愿不可用。

    作者回复: 结合CAP进行分析,赞! Redis本身不支持强一致性,因为保证强一致性的代价太大,从CAP角度看,就是放弃C,选择A和P。 min-slaves-to-write 和 min-slaves-max-lag的设置,是为了避免主从数据不一致程度加重。两个参数起作用时,相当于对主库做降级,放弃了A,选择C和P。

    2020-12-10
    79
  • Geek_d1eece
    老师用的画图工具叫什么?

    编辑回复: PPT哈~

    2020-11-05
    2
  • Kaito
    假设我们将 min-slaves-to-write 设置为 1,min-slaves-max-lag 设置为 15s,哨兵的 down-after-milliseconds 设置为 10s,哨兵主从切换需要 5s。主库因为某些原因卡住了 12s,此时,还会发生脑裂吗?主从切换完成后,数据会丢失吗? 主库卡住 12s,达到了哨兵设定的切换阈值,所以哨兵会触发主从切换。但哨兵切换的时间是 5s,也就是说哨兵还未切换完成,主库就会从阻塞状态中恢复回来,而且也没有触发 min-slaves-max-lag 阈值,所以主库在哨兵切换剩下的 3s 内,依旧可以接收客户端的写操作,如果这些写操作还未同步到从库,哨兵就把从库提升为主库了,那么此时也会出现脑裂的情况,之后旧主库降级为从库,重新同步新主库的数据,新主库也会发生数据丢失。 由此也可以看出,即使 Redis 配置了 min-slaves-to-write 和 min-slaves-max-lag,当脑裂发生时,还是无法严格保证数据不丢失,它只能是尽量减少数据的丢失。 其实在这种情况下,新主库之所以会发生数据丢失,是因为旧主库从阻塞中恢复过来后,收到的写请求还没同步到从库,从库就被哨兵提升为主库了。如果哨兵在提升从库为新主库前,主库及时把数据同步到从库了,那么从库提升为主库后,也不会发生数据丢失。但这种临界点的情况还是有发生的可能性,因为 Redis 本身不保证主从同步的强一致。 还有一种发生脑裂的情况,就是网络分区:主库和客户端、哨兵和从库被分割成了 2 个网络,主库和客户端处在一个网络中,从库和哨兵在另一个网络中,此时哨兵也会发起主从切换,出现 2 个主库的情况,而且客户端依旧可以向旧主库写入数据。等网络恢复后,主库降级为从库,新主库丢失了这期间写操作的数据。 脑裂产生问题的本质原因是,Redis 主从集群内部没有通过共识算法,来维护多个节点数据的强一致性。它不像 Zookeeper 那样,每次写请求必须大多数节点写成功后才认为成功。当脑裂发生时,Zookeeper 主节点被孤立,此时无法写入大多数节点,写请求会直接返回失败,因此它可以保证集群数据的一致性。 另外关于 min-slaves-to-write,有一点也需要注意:如果只有 1 个从库,当把 min-slaves-to-write 设置为 1 时,在运维时需要小心一些,当日常对从库做维护时,例如更换从库的实例,需要先添加新的从库,再移除旧的从库才可以,或者使用 config set 修改 min-slaves-to-write 为 0 再做操作,否则会导致主库拒绝写,影响到业务。
    2020-11-04
    24
    295
  • test
    课后问题:仍然可能会发生数据丢失。究其原因是redis内部没有共识算法保证数据同步,写数据的时候只是写入主库即可返回成功,数据同步到从库是通过异步处理的。
    2020-11-04
    1
    14
  • 李二木
    最欣赏的是排查分析问题的过程。
    2020-11-04
    13
  • snailshen
    老师您好,防止脑裂我认为有2点需要注意: 1可以考虑把多个sentinel节点部署到不同的机房,减少由于网络原因导致的误判。 2.redis master主节点主机,避免高负载,部署时留有一些冗余 关于min-slaves-to-write,min-slaves-max-lag这两个配置,主要是解决主从同步数据一致性问题的,尽量减少主从同步的数据不一致,我觉得不能从根本上通过这两个参数解决脑裂。比如master和slave的网络很好,那么这两个参数失效,如果这个时候3个sentinel节点的到master的网络都异常并且这些节点到slave网络良好,那么一样会触发主从切换,造成脑裂。我是这样理解的,希望老师指正!
    2020-11-04
    9
  • escray
    其实我不太关心脑裂,但是我对于发现数据丢失之后的故障排查思路比较感兴趣。 1. 确认数据同步是否有问题,检查主从库复制进度差值(master_repl_offset 和 slave_repl_offset) 2. 排查客户端日志,发现脑裂 3. 发现原主库假故障导致脑裂 利用 min-slaves-to-write 和 min-slaves-max-lag 两个配置项搭配使用,可以避免脑裂。参考文中的例子,min-slaves-to-write 设置为 1,就是说只要有一个从库无法在 min-slaves-max-lag 的时间内发送代表主从复制完成的 ACK 消息,原主库就不能再接收客户端请求了。 假设从库有 K 个,那么 min-slaves-to-write 就设置为 K/2+1,其实超过半数的从库,再结合哨兵机制的 quorum,就可以避免脑裂。 对于课后题,按照题目的条件,min-slaves-to-write 设为 1,min-slaves-max-lag 设为 15s,哨兵 down-after-milliseconds 设置为 10s,哨兵主从切换 5s,主库卡住 12s,我觉的可能不会发生脑裂。 主库卡住 12s,哨兵已经判定原主库下线了,而因为 min-slave-to-write 和 min-slaves-max-lag 的设置,只有超过 15s,才会拒绝原主库接受客户端请求,也就是说从第 12s 到 15s 之间,原主库可以接受客户端请求,而 15s 后,主从切换完成,新主库开始接收客户端请求,而原主库在 12s 后接收的请求可以同步到新主库。 看了课代表的答案,其实我也纠结,原主库从 12s 到 15s 接收到的请求能否同步到新主库。 课代表对于只有一个从库,且设置了 min-slave-to-write 为 1 的时候,运维操作注意事项的提醒很有价值。
    2021-04-02
    5
  • 我很迪奥
    不太明白为什么需要引入min-slaves-to-write,min-slaves-max-lag这两个参数来避免脑裂,为什么不在哨兵认为主库客观下线的时候,就禁止主库的写操作。
    2020-12-21
    11
    4
  • 与君共勉
    min-slaves-max-lag是不是一般要设置成比down-after-milliseconds小的值最好?
    2020-11-04
    1
    3
  • Geek_3d51a3
    redis执行slave of之后,就变成了只读实例,写入会报错
    2021-02-19
    2
收起评论
显示
设置
留言
26
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部