57 / 77
Gossip 协议
Trying to squash a rumor is like trying to unring a bell.
Gossip 最早由施乐公司(Xerox,现在可能很多人不了解施乐了,或只把施乐当一家复印产品公司看待,这家公司是计算机许多关键技术的鼻祖,图形界面的发明者、以太网的发明者、激光打印机的发明者、MVC 架构的提出者、RPC 的提出者、BMP 格式的提出者……) Palo Alto 研究中心在论文《Epidemic Algorithms for Replicated Database Maintenance》中提出的一种用于分布式数据库在多节点间复制同步数据的算法。从论文题目中可以看出,最初它是被称作“流行病算法”(Epidemic Algorithm)的,只是不太雅观,今天 Gossip 这个名字已经用得更为普遍了,除此以外,它还有“流言算法”、“八卦算法”、“瘟疫算法”等别名,这些名字都是很形象化的描述,反应了 Gossip 的特点:要同步的信息如同流言一般传播、病毒一般扩散。
笔者按照习惯也把 Gossip 也称作是“共识协议”,但首先必须强调它所解决的问题并不是直接与 Paxos、Raft 这些共识算法等价的,只是基于 Gossip 之上可以通过某些方法去实现与 Paxos、Raft 相类似的目标而已。一个最典型的例子是比特币网络中使用到了 Gossip 协议,用它来在各个分布式节点中互相同步区块头和区块体的信息,这是整个网络能够正常交换信息的基础,但并不能称作共识;比特币使用工作量证明(Proof of Work,PoW)来对“这个区块由谁来记账”这一件事情在全网达成共识,这个目标才可以认为与 Paxos、Raft 的目标是一致的。
下面,我们来了解 Gossip 的具体工作过程。相比 Paxos、Raft 等算法,Gossip 的过程十分简单,它可以看作是以下两个步骤的简单循环:
如果有某一项信息需要在整个网络中所有节点中传播,那从信息源开始,选择一个固定的传播周期(譬如 1 秒),随机选择它相连接的 k 个节点(称为 Fan-Out)来传播消息。
每一个节点收到消息后,如果这个消息是它之前没有收到过的,将在下一个周期内,选择除了发送消息给它的那个节点外的其他相邻 k 个节点发送相同的消息,直到最终网络中所有节点都收到了消息,尽管这个过程需要一定时间,但是理论上最终网络的所有节点都会拥有相同的消息。
Gossip 传播示意图(图片来源)
同时我们也很容易找到 Gossip 的缺点,消息最终是通过多个轮次的散播而到达全网的,因此它必然会存在全网各节点状态不一致的情况,而且由于是随机选取发送消息的节点,所以尽管可以在整体上测算出统计学意义上的传播速率,但对于个体消息来说,无法准确地预计到需要多长时间才能达成全网一致。另外一个缺点是消息的冗余,同样是由于随机选取发送消息的节点,也就不可避免的存在消息重复发送给同一节点的情况,增加了网络的传输的压力,也给消息节点带来额外的处理负载。
达到一致性耗费的时间与网络传播中消息冗余量这两个缺点存在一定对立,如果要改善其中一个,就会恶化另外一个,由此,Gossip 设计了两种可能的消息传播模式:反熵(Anti-Entropy)和传谣(Rumor-Mongering),这两个名字都挺文艺的。熵(Entropy)是生活中少见但科学中很常用的概念,它代表着事物的混乱程度。反熵的意思就是反混乱,以提升网络各个节点之间的相似度为目标,所以在反熵模式下,会同步节点的全部数据,以消除各节点之间的差异,目标是整个网络各节点完全的一致。但是,在节点本身就会发生变动的前提下,这个目标将使得整个网络中消息的数量非常庞大,给网络带来巨大的传输开销。而传谣模式是以传播消息为目标,仅仅发送新到达节点的数据,即只对外发送变更信息,这样消息数据量将显著缩减,网络开销也相对较小。