raft协议,leader在commit了一条日志后,立刻挂了,那其他节点如何处理这条日志?

raft论文提到一旦日志被commit,那么大部分节点都会拥有这条日志,但问题是大部分节点只有当leader做了commit之后,才会commit到自己的状态机吧。假若leader在commit完一条日志后马上挂了,那其他节点肯定不知道这条日志已经被commit,那后续新的leader也不会把这条日志放进commited log中去。请问这样日志的一致性是怎么保证的? raft不是不能改写已经被commit的日志吗?

阅读 3.2k
3 个回答

挂了的话,等恢复就好了。自动复制的时候,就能发现自己的index不是最新的对不上,进行恢复

1、首先给你一个网址:http://thesecretlivesofdata.c...,能够更加生动的看到Log Replication的过程。
2、Commit的定义是当集群中大部分的节点(一半以上)响应了Leader的Log Replication操作之后才会被Commited。否则,Leader是不会像Client发送提交成功的响应的。提交操作并未真正Commit,Leader会被阻塞在这里。
3、这种情况的发生一般来说都是因为Leader挂掉了或者网络分区了。Leader挂掉了的话在一个HeartBeat Timeout后系统会Re-select,新的Leader会更新自己的term-id,这时候Client一般是会重试的,也就是会向新的Leader提交成功。
4、当Leader恢复或者分区消失,恢复后的Leader发现集群存在更新的term-id,它会放弃leader地位并主动向新的leader进行同步,从而整个集群恢复到一致状态。

  1. 根据领导人完备性原则,已经提交的消息一定会在下一次的Leader中出现。
    图片
  2. 假若leader在commit完一条日志后马上挂了,新leader虽然不知道这条日志已经被commit,不会立即主动提交,但是它持有这条日志,当其发现这条日志复制到大多数follower上时,会进行commit
    图片
  3. 前面两条可以保证保证已提交消息不丢,接着要保证消息不重复。客户端每次提交操作的时候会对操作有一个唯一的id,然后发现leader挂了,对新的leader重试的时候也会带上同一个操作id,然后发现新leader发现id存在,不会重复操作,而是会把之前leader的消息返回。
    图片

最大的问题还是客户端如果宕机,没来得及重试,可能导致数据提交成功,但是客户端不感知,这就要想办法在客户端持久化序列号id,保证宕机重启后仍能提交。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进