分布式协议与算法实战——拜占庭将军问题(有叛徒的情况下,如何才能达成共识((笔记)))

拜占庭将军问题(The Byzantine Generals Problem),其实是借拜占庭将军的故事展现了分布式共识问题,还探讨和论证了解决的办法。实际上,它是分布式领域最复杂的一个容错模型,一旦搞懂它,你就能掌握分布式共识问题的解决思路,还能更深刻地理解常用的共识算法,在设计分布式系统的时候,也能根据场景特点选择适合的算法,或者设计适合的算法了。
以六国抗秦重讲拜占庭算法 六国抗秦的困境
在现实情况中可能存在诸侯国暗通秦国,发送误导性作战信息、信使被截杀、信使被间谍替换的情况。在网络世界中存在节点崩溃、网络故障、丢包(以上是非拜占庭错误)和不遵循协议规则的,如验证器可以延迟或拒绝中继网络中的消息、领导者可以提出无效块、被中间人攻击、攻击者在恶意伪造信息或者节点可以向不同的对等体发送不同的消息甚至恶意节点之间相互协作制造错误(以上是拜占庭错误)在以上情况中如果达成共识?
二忠一叛难题
先假设齐、楚、燕3个国家攻打秦国,假设只有半数以上的将军参与进攻才能击败敌人,在这个期间,将军们彼此之间需要通过信使传递消息,然后协商一致之后,才能在同一时间点发动进攻。
正常情况下:
  • 齐国根据侦察信息,决定撤退
  • 楚和燕根据侦察信息,决定进攻
根据规则,应该三支军队一块进攻。但假设燕国叛变,向齐国发送撤退消息,向楚国发送进攻消息,自己撤退。最终按照规则也能达成一致性作战方案,但最终楚国落入虎口。
拜占庭算法 口信消息型拜占庭问题之解
首先,通过数学证明不借助其他技术手段三个将军无法解决上述问题,需要多引进一个诚实将军,变成4位将军进行作战讨论。同时,4位将军约定默认命令为撤退,需要经过两轮协商
第一轮:
  • 先发送作战信息的将军作为指挥官,其他的将军作为副官;
  • 指挥官将他的作战信息发送给每位副官;
  • 每位副官,将从指挥官处收到的作战信息,作为他的作战指令。如果没有收到作战信息,将把默认的“撤退”作为作战指令;
第二轮
  • 除了第一轮的指挥官外,剩余的 3 位将军将分别作为指挥官,向另外 2 位将军发送作战信息;
  • 然后,这 3 位将军按照“少数服从多数”,执行收到的作战指令。
总结 如果叛将人数为 m,将军人数不能少于 3m + 1 ,那么拜占庭将军问题就能解决了。
【分布式协议与算法实战——拜占庭将军问题(有叛徒的情况下,如何才能达成共识((笔记)))】这个算法有个前提,也就是叛将人数 m,或者说能容忍的叛将数 m,是已知的。在这个算法中,叛将数 m 决定递归循环的次数(也就是说,叛将数 m 决定将军们要进行多少轮作战信息协商),即 m+1 轮(所以,你看,只有楚是叛变的,那么就进行了两轮)。你也可以从另外一个角度理解:n 位将军,最多能容忍 (n - 1) / 3 位叛将。
签名消息型拜占庭问题之解 还可以通过签名的方式,在不增加将军人数的情况下,解决二忠一叛的难题。首先,作战指挥官要通过印章、虎符等信物,实现这样几个特性:
  • 忠诚将军的签名无法伪造,而且对他签名消息的内容进行任何更改都会被发现;
  • 任何人都能验证将军签名的真伪。
在互联网中数字证书具有以上特性。这时,任何人修改信息都可以看到,通过签名机制约束叛将的叛变行为,任何叛变行为都会被发现,也就会实现无论有多少忠诚的将军和多少叛将,忠诚的将军们总能达成一致的作战计划。

    推荐阅读