Raft 共识协议要求节点有一个复制日志,而我所知道的所有实现都要求每个节点都有一个持久的本地存储来保存日志。在云原生环境中,例如 Kubernetes,如果节点没有任何持久卷,则更容易管理,因为它们可以部署为普通的
Deployment
,而持久卷需要 StatefulSet
,这会带来一些额外的复杂性,并且局限性。
我想知道Raft是否可以成功地应用于节点共享公共日志的场景中,它们可以追加和读取该日志,并且可以分配单调递增的记录id。这可以通过 Kafka 主题轻松实现,但其他选项也是可能的。
这样做会产生什么影响?换句话说,我想了解选择使用共享日志而不是复制日志来实现 Raft 共识的权衡。
为了说明这是如何工作的,下面是基于 Raft 的复制键值存储如何与共享日志配合使用的草图(括号中是基于 Kafka 主题的实现的详细信息):
Put(K,V)
交易追加到共享日志中(发布到Kafka主题)。Put(K,V)
消息(从 Kafka 主题消费)并更新其内存中的键值存储。关注者可用于满足客户的
Get(K)
请求。如果最终一致性是可以接受的,那么任何跟随者只要处理了从领导者那里收到的最新 id 对应的消息就可以响应客户端。如果需要 read-your-writes,那么客户端可以存储从领导者那里收到的消息 id 并将其发送给跟随者。在这种情况下,追随者将阻塞,直到它收到并处理来自日志的相应消息。
“Raft 共识协议要求节点拥有复制日志”——这实际上是相反的,raft 协议的存在就是为了使该日志成为可能。如果有人有办法获得线性日志 - 就不需要筏。
raft(或其他共识协议)的目标是就某件事达成一致。在 raft 情况下,几个完全独立(无资源共享)的节点可能就事件流达成一致。因此,如果系统已经拥有获取此类流的工具,则根本不需要 raft。在kafka示例中,每个客户端都可以直接写入kafka流,不需要有专门的领导者。
有趣的事实:Kafka 在幕后间接使用共识算法来管理可用性。请参阅此处的详细信息https://kafka.apache.org/documentation/#design_replicatedlog(他们谈论通过共识管理配置的部分)