Definition
最弱的广播类型称为先进先出(FIFO)广播。在这个模型中,由同一节点发送的信息按照发送的顺序传递。例如下图中,\(m_{1}\) 必须在 \(m_{3}\) 之前被传递,因为它们都是由 \(A\) 发送的。然而,\(m_{2}\) 可以在 \(m_{1}\) 和 \(m_{3}\) 之前、之间或之后的任何时间被传递。
同一个节点发送的消息必须要按照发送的顺序传递,不同节点发送的消息可以是任意的顺序,比如 \((m_{2}, m_{1}, m_{3})\),\((m_{1}, m_{2}, m_{3})\) 或者 \((m_{1}, m_{3}, m_{2})\)。
关于这些广播协议的另一个细节:我们假设每当一个节点广播一个消息时,它也会将该消息传递给自己(在上图中用回环箭头表示)。一个节点知道它自己广播了什么消息,所以传递给自己看似没有必要,但在 Total order broadcast 中是需要这个步骤。
上图中的执行示例是有效的先进先出「广播」,但它违反了因果性:虽然 \(B\) 在接收了 \(m_{1}\) 之后才广播的 \(m_{2}\),但节点 \(C\) 在 \(m_{1}\) 之前就传递了 \(m_{2}\)。Causal broadcast 提供了一个比 FIFO broadcast 更严格的排序属性。顾名思义,它确保信息按因果顺序传递:也就是说,如果一条信息的广播发生在另一条信息的广播之前,那么所有节点必须按这个顺序传递这两条信息。如果两个消息是同时广播的,一个节点可以按任何一个顺序传递它们。
FIFO broadcast algorithm
节点 \(N_{i}\) 发送的每个 FIFO broadcast 消息都会附带发送节点编号 \(i\) 和一个序列号(该节点发送消息对应的序列号,第一条消息对应为 0,第二条消息对应为 1)。每个节点的本地状态由序列号 \(sendSeq\)(计算该节点广播的消息数量)、\(delivered\)(一个向量,每个节点有一个条目,统计了每个节点发送消息并传递到该节点的数量)和 \(buffer\)(一个缓存,用于保留消息直到它们准备好被传递给 Application,也就是 Receiving versus delivering 中提到的 deliver 阶段)组成。该算法检查来自任何发送者的与预期的下一个序列号相匹配的消息,然后递增该序列号,确保来自每个特定发送者的消息按照序列号递增的顺序被传递。
Summary
FIFO broadcast 的保持消息顺序的原理和 Lamport clocks 很相似,都是用递增的整数来确定同一个节点上的消息传递的顺序,\(deliver\) 是个存放着所有节点 \(sendSeq\) 的向量,存放于每个节点,配合 \(sendSeq\) 控制来自同一个节点的消息传递的顺序。