技术文章:分布式系统模式之Consistent Core

java达人
关注

寻找 Leader

串行化和线性化

当 follower 服务器处理读取请求时,由于 leader 的最新提交尚未到达跟随者,客户端可能会获得陈旧数据。客户端接收更新的顺序仍保持不变,但是更新可能不是最新的。与线性化相对,这是串行化保证。线性化可确保每个客户端都获得最新更新。客户端仅需要读取元数据并且可以暂时容纳过时的元数据时,便可以使用串行化保证。对于诸如 Lease 之类的操作,需要严格线性化。

如果将 leader 从集群中分割出去,则客户端可以从 leader 获得陈旧的值,Raft描述了一种提供线性化读取的机制。参见例子etcd 的readIndex实现。

分割的 follower 可能会发生类似的情况。follower 可能已分割,可能未将最新值返回给客户端。为确保 follower 未分割且与 leader 保持最新,他们需要查询 leader 以了解最新更新,并等到收到最新更新后再对客户端进行响应,请参阅proposed kafka design例子。

所有操作都必须在 leader 上执行,这很重要,因此客户端库需要首先找到leader 服务器。有两种方法可以满足此要求。

consistent core中的follower服务器知道当前的 leader,因此,如果客户端连接到 follower,则它可以返回leader 的地址。然后,客户端可以直接连接在响应中标识的 leader。应当注意,当客户端尝试连接时,服务器可能处于leader选举状态。在这种情况下,服务器无法返回leader地址,客户端需要等待并尝试另一台服务器。

服务器可以实现转发机制,并将所有客户端请求转发给 leader。这允许客户端连接到任何服务器。同样,如果服务器处于leader 选举中,则客户端需要重试,直到leader选举成功并建立了合法的 leader 为止。

Zookeeper 和 etcd 之类的产品之所以采用这种方法,是因为它们允许follower 服务器处理一些只读请求。当大量客户端是只读客户端时,这避免了leader 的瓶颈。这样可以让客户端根据请求类型减少连接到leader 或follower 的复杂性。

找到leader的一种简单机制是尝试连接到每个服务器并尝试发送请求,如果服务器不是leader,则服务器会重定向响应。

private void establishConnectionToLeader(List

仅建立TCP连接是不够的,我们需要知道服务器是否可以处理我们的请求。因此,客户端向服务器发送一个特殊的连接请求,以确认服务器是否可以处理请求或重定向到 leader 服务器。

private RequestOrResponse sendConnectRequest(SingleSocketChannel socketChannel) throws IOException {
   RequestOrResponse request
           = new RequestOrResponse(RequestId.ConnectRequest.getId(), "CONNECT", 0);
   try {
       return socketChannel.blockingSend(request);
   } catch (IOException e) {
       resetConnectionToLeader();
       throw e;
   }
}

如果现有的leader失败,同样的技术被用来从集群中识别新当选的 leader。

连接后,客户端将维护到leader 服务器的Single Socket Channel。

处理重复请求

在失败的情况下,客户端可以尝试连接到新的leader,重新发送请求。但是,如果那些请求在失败之前已经由失败的leader 处理过,则可能会导致重复。因此,在服务器上具有一种机制可以忽略重复的请求,这一点很重要。Idempotent Receiver 模式用于实现重复检测。

使用 Lease 可以完成一组服务器之间的协调任务。可以使用相同的方法来实现组成员身份和故障检测机制。

State Watch 用于获取有关元数据或时间限制租约更改的通知。

例子

众所周知,谷歌使用[chubby]锁服务进行协调和元数据管理。

[kafka]使用[zookeeper]来管理元数据,并为集群主服务器做出决策,例如选择 leader。kafka 提议的体系结构更改将用其自己的基于[raft]的控制器集群代替Zookeeper。

[bookkeeper]使用 Zookeeper 管理集群元数据。

[kubernetes]使用[etcd]进行协调,管理集群元数据和组成员信息。

[hdfs],[spark],[flink]等所有大数据存储和处理系统都使用[zookeeper]来实现高可用性和集群协调。

说明

注1:因为整个集群都依赖于 Consistent Core,所以了解所使用的一致性算法的细节至关重要。在某些棘手的网络分区情况下,一致性实现可能会遇到活跃性问题。例如,除非特别注意,否则Raft集群可能会被分割的服务器破坏,分割的服务器会不断触发leader选举。最近在 Cloudflare 发生的事件是一个值得学习的好例子。


声明: 本文由入驻OFweek维科号的作者撰写,观点仅代表作者本人,不代表OFweek立场。如有侵权或其他问题,请联系举报。
侵权投诉

下载OFweek,一手掌握高科技全行业资讯

还不是OFweek会员,马上注册
打开app,查看更多精彩资讯 >
  • 长按识别二维码
  • 进入OFweek阅读全文
长按图片进行保存