分布式一致性协议三部曲-从paxos幽灵复现看Raft实现原理

幽灵复现Mutlti-Paxos下存在Leader切换情况,因而可能出现下面的场景 第一轮中A被选为 Leader,写下了 1-10 号日志,其中 1-5 号日志形成了多数派,并且已给客户端应答,而对于 6-10 号日志,客户端超时未能得到应答。 第二轮,A 宕机,B 被选为 Leader,由于 B 和 C 的最大的 LogID 都是 5,因此 B 不会去重确认 6 ...
摘要由CSDN通过智能技术生成

幽灵复现

 

Mutlti-Paxos下存在Leader切换情况,因而可能出现下面的场景

  • 第一轮中A被选为 Leader,写下了 1-10 号日志,其中 1-5 号日志形成了多数派,并且已给客户端应答,而对于 6-10 号日志,客户端超时未能得到应答。

  • 第二轮,A 宕机,B 被选为 Leader,由于 B 和 C 的最大的 LogID 都是 5,因此 B 不会去重确认 6 - 10 号日志,而是从 6 开始写新的日志,此时如果客户端来查询的话,是查询不到上一轮 6 - 10 号 日志内容的,此后第二轮又写入了 6 - 20 号日志,但是只有 6 号和 20 号日志在多数派。

  • 第三轮,A 又被选为 Leader,从多数派中可以得到最大 LogID 为 20,因此要将 7 - 20 号日志执行重确认,其中就包括了 A 上的 7-10 号日志,这次重确认会发现7-20都已形成多数派,因而之后客户端再来查询的话,会发现上次查询不到的 7 - 10 号日志又像幽灵一样重新出现了。

    该问题发生的原因就是日志非顺序确认(形成多数派)。Multi-Paxos协议里,每条日志是一个Paxos实例,是完全独立的,同一个Leader下的日志写入有顺序,多数派确认是异步的,不一定是顺序的。这个有点像多线程并发执行(日志同步),同一个线程里的顺序是确定,线程之间的执行顺序谁知道呢?比如上面,就出现1~6, 20已经形成多数派确认了,7~19还未形成多数派。就会出现客户端开始访问不到第7条记录,但是能访问到第20条记录,等到后面7重确认后,客户端又能访问到第7条日志了。如果这些日志之间没有任何顺序关联,这倒也不是问题。但是现实场景下,几乎都是顺序执行事务的场景,比如数据库日志。具体到上面的案例,假设日志6是"A给B转账100万", A,B后面查询发现这笔转账未成功(未达到多数派),因而再次发起转账(日志20), 然后日志20被确认,即执行了100万金额的操作。不曾想在第三轮,日志6被再次确认,A又被转了100万,结果导致A被转了200万这一错误。那该如何解决这个问题呢?

  • 死等法

    在第二轮,客户端在请求日志7结果时,系统应该返回未确定状态而不是失败状态,这样客户端知道未确定状态下是不会发起新的和7有关联的日志的,即日志20肯定和7无关,那么他们的确认先后顺序自然也无关紧要,即不解决幽灵复现,但也不会导致损失。当然这种应用场景有限,很少有客户能忍受一个不确定的状态?你发起了转账结果系统告诉你不确定,也不知道什么时候能确定。

  • 丢弃未被确认的老日志

    新任 Leader 在完成日志重确认,开始写入新的 Log 之前,先写出一条被称为 StartWorking 的日志,这条日志的内容中记录了当前 Leader 的 EpochID( 可以使用 Proposalid 的值),并且 Leader 每写一条日志都在日志内容中携带现任 Leader 的 EpochID。回放时,经过了一条 StartWorking 日志之后,再遇到 EpochID 比它小的日志,就直接忽略掉,比如按照上面例子画出的这张图,7 - 19 号日志要在回放时被忽略掉。

 

这个是Multi-Paxos实现采用的方案。

上面讨论的所有前提是在一个Leader的周期里,不会存在开始日志7未形成多数派,突然又形成多数派的情况,如果有这种情况,上面的方案也解决不了。其实这个本身比较好满足的,因为必须要有新Leader,才会有变数, 且才会重新确认,才会导致日志7状态从未确认到确认。
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值