定义

常见的一致性问题

非人为恶意的意外投票过程
非人为恶意篡改可归类为信鸽半路挂掉、信鸽迷路、信鸽送错目的地、信鸽送信途中下雨导致信件内容模糊、接收信件的人不在家、天气变化信鸽延迟送达等等。这些对应到分布式系统面临的问题就是:消息丢包、网络拥堵、消息延迟、消息内容校验失败、节点宕机等。

这种场景可能会丢失消息,或者有消息重复,但不存在错误消息或者伪造消息的情况

人为恶意篡改投票过程
人为恶意篡改包括“精神分裂式投票”,中继篡改上一个村落的投票信息。对应到分布式系统面临的问题就是:消息被伪造、系统安全攻击等等。发生的人为恶意篡改的过程就可以称之为系统发生了拜占庭错误(Byzantine Fault),如果系统可以容忍拜占庭错误而不至于崩溃,也就是在发生系统被恶意篡改的情况下仍然可以达成一致,我们将这样系统称作为做拜占庭容错系统。

一致性是指在某个分布式系统中,任意节点的提案能够在约定的协议下被其他所有节点所认可。

这里的“认可”表示所有节点对外呈现的信息一致,而不是对信息的内容认可。

故事描述

https://time.geekbang.org/column/article/195662

在拜占庭帝国,9 位将军分别率领一支军队要共同围困一座城市。但是这座城市军事实力很强大,如果不协调统一将军们的行动策略,部分军队进攻、部分军队撤退会造成围困失败。因此,各位将军必须通过投票达成一致策略,少数服从多数,要么一起进攻,要么一起撤退。
如何达成共识,制定统一的作战计划呢?

也就是说,如何在可能有误导信息的情况下,采用合适的通讯机制,让多方达成共识,制定一致性的结果?

两忠一叛的难题

以齐、楚、燕三国攻击秦国为例子

一天在讨论第二天是进攻还是撤退,齐(A)决定撤退,楚(B)和燕国(C)决定撤退,根据少数服从多数的原则,最终三支队伍就会进攻

但是就会出现一个问题,如果有人改变了想法,暗通秦国,就会出现作战计划不一致的情况

例如A向B和C发送撤退的信息,C向A和B发送了进攻的信息,这个时候ABC根据自己的意向和别人的意向,形成了1:1打平的情况,那么B发送给AC的意向将会决定最终的作战方案,最终形成2:1

但是如果有人叛变,B向A发送撤退,向C发送进攻
那么在A看来,撤退大于进攻,在C看来,进攻大于撤退

根据最先定义的少数服从多数的原则,就会出现C单独进攻的情况,最终出现混乱

从上面可以看出,一个叛徒通过发送给其他方不一致的消息,就能够干扰他方的计划,从而带来不好的影响

口信消息型解法

在ABC三方中,增加一方X,能够增加讨论中忠诚的数量,然后事先约定如果没有收到命令就执行预设的默认命令,并且还要进行两轮的作战信息协商

第一轮

  • 先发送作战信息的为指挥官,其他的作为副官
  • 指挥官将他的作战信息发送给每一个副官
  • 副官收到指挥官的作战信息,没收到就以默认为信息

第二轮

  • 除了第一轮的指挥官之外,其他的三位将军分别作为指挥官,向另外两位将军发送作战信息(第一轮收到的消息)
  • 这三位将军按照少数服从多数,执行收到的作战指令

分析

如果一开始是忠诚的X先发送进攻消息,那么ABC都收到进攻
第二轮,A和C发送给BC和AB进攻,B发送给AC撤退,但是这样还是少数服从多数,2:1

如果一开始是叛徒B,向X发送进攻,向AC发送撤退的消息
第二轮,X发送进攻给AC,A、C都发送撤退给BC以及Ab,那么最终收到的信息都是撤退2,进攻1

如果一开始是叛徒B,向X发送撤退,向AC发送进攻的消息
第二轮,X发送撤退给AC,A、C都发送进攻给BC以及AB,那么最终收到的信息都是撤退1,进攻2

也就是说,无论叛徒如何捣乱,最终多方都会执行对外保持一致的作战计划,达成共识

总结

总的来说,这个解决方法就是兰伯特在论文《The Byzantine Generals Problem》中提到的口信消息型拜占庭问题之解:如果叛将人数为 m,将军人数不能少于 3m + 1 ,那么拜占庭将军问题就能解决了

这个算法的前提是,叛徒人数m,也就是最大能容忍的叛徒人数,是已知的,叛徒数量m决定了所有人要进行的协商次数,也就是m+1次,那么也就是说n个将军,最多能够容忍(n-1)/3个叛徒

这个算法也有一个限制,限制了将军总人数必须不小于3m+1,所以在上面ABC的情况下,存在了B为叛徒,也必须要增加一个忠诚的将军
而且按照递归一直做下去,需要m+1轮,也就是有m!量级的消息需要发送

签名消息解法

通过签名的方式,在不增加将军人数的情况下,解决二忠一叛的难题

  • 忠诚将军的签名无法被伪造,对于他人签名消息的内容进行任何更改都会被发现
  • 任何人都能够验证签名的真伪

A说进攻,发送给BC,然后B说AB要撤退发送给AC,然后C收到只会承认A会进攻的消息

如果B先发送消息,AB将会按照一定的规则,在排序后的所有已经接收到的指令当中选取一个指令,进行执行,最终执行一致的作战计划,一致就行了,这样大家的行为都是一致的就可以

签名消息拜占庭问题之解,虽然实现了计划的一致性,但它不关心达成共识的结果是什么。

如何基于签名消息实现作战计划的一致性

https://time.geekbang.org/column/article/215640

区块链共识算法

工作量证明PoW或者权益证明PoS说明了如何遵循这些规则以达到共识

这些算法也并不能完全抵抗拜占庭故障,但是由于高成本的挖矿过程和底层加密技术,工作量证明已被证明是区块链网络中的一种最安全可靠的方法。从这个意义上说,由中本聪设计的工作量证明共识算法被许多人认为是拜占庭容错最高明的解决方案之一。

总结

  • 故事里的各位将军,可以理解为计算机节点
  • 忠诚的将军,你可以理解为正常运行的计算机节点
  • 叛变的将军,你可以理解为出现故障并会发送误导信息的计算机节点
  • 信使被杀,可以理解为通讯故障、信息丢失
  • 信使被间谍替换,可以理解为通讯被中间人攻击,攻击者在恶意伪造信息和劫持通讯。

叛变的节点除了故障行为,也存在恶意行为,所以在区块链技术中也必须使用拜占庭容错算法