分布式笔记(01)— 分布式 CAP 理论及原理

1. 分布式中的 CAP 理论

CAP 原理是描述分布式系统下节点数据同步的基本定理,分别指

  • Consistency(一致性)

指数据一致性,表示一个系统的数据信息(包括备份数据)在同一时刻都是一致的。在分布式系统下,同一份数据可能存在于多个不同的实例中,在数据强一致性的要求下,修改其中一份数据后必须同步到它的所有备份中。在数据同步的任何时候,都需要保证所有对该份数据的请求将返回同样的状态。

  • Availability(可用性)

指服务可用性,要求服务在接收到客户端请求后,都能够给出响应。服务可用性考量的是系统的可用性,要求系统在高并发情况和部分节点宕机的情况下,系统整体依然能够响应客户端的请求。

  • Partition tolerance(分区容错性)

指分区容忍性。在分布式系统中,不同节点之间通过网络进行通信。由于网络的不可靠性,位于不同网络分区的服务节点可能会通信失败,如果系统能够容忍这种情况,说明它是满足分区容忍性的。如果系统不能满足,将会限制分布式系统的扩展性,即服务节点的部署数量和地区都会受限,也就违背了分布式系统设计的初衷,所以一般来说分布式系统都会满足分区容忍性。
CAP

这三个要素最多只能同时实现两点,不能三者兼顾。

基于分布式系统的基本特质,P(分区容错性)是必须要满足的,所以接下来需要考虑满足 C(一致性)还是 A(可用性)。

但是在满足了分区容忍性的前提下,分布式系统并不能同时满足数据一致性和服务可用性。

假设服务 A 现在有两个实例 A1A2,它们之间的网络通信出现了异常,基于分区容忍性,这并不会影响 A1A2 独立的正常运行。假如此时客户端请求 A1,请求将数据 BB1 状态修改为 B2,由于网络的不可用,数据 B 的修改并不能通知到实例 A2

如果此时另一个客户端向 A2 请求数据 B,如果 A2 返回数据 B1,将满足服务可用性,但并不能满足数据一致性;如果A2 等待 A1 的通知后才返回数据 B 的正确状态,虽然满足了数据一致性,但并不能响应客户端请求,违背了服务可用性的指标。

在类似银行之类对金额数据要求强一致性的系统中,要优先考虑满足数据一致性;而在大众网页之类的系统中,用户对网页版本的新旧不会有特别的要求,在这种场景下服务可用性会高于数据一致性。

BASE理论

2. 分布式原理

2.1 客户端

当 RPC 服务部署在多个节点上时,客户端得到的是一个服务列表,有多个 IP 端口对。客户端的连接池可以随机地挑选任意的 RPC 服务节点进行连接。

每个服务节点应该有个权重值,当所有节点的权重值一样时,它们的流量分配就是均匀的。如果某个节点的相对权重值较小,它被客户端选中的概率也会相对比较小。

class RPCNode {
    String addr;  // 服务地址
    int weight; // 节点权重
}

class RPCCluster {
    RPCNode[] nodes; // 节点列表
    
    Node random(); // 按权重随机挑选节点
}

2.2 容灾

当有一个服务节点挂掉时,客户端需要采取一定的策略避免请求失败。当请求失败时,客户端还要进行重试,但是也不可以无限重试,要有一定的重试策略。

比如当节点挂掉时,将失效节点摘除,放置到失效节点列表中。然后每隔一段时间检查失效节点是否恢复了,如果恢复了,那就从失效节点中移除,再将节点地址重新加入到有效节点列表中。那如何判断节点真的挂掉了呢,一般需要设置一个时间窗口,统计在一定时间窗口里出现的错误数量。如果这个数量过大,那就意味着失效了。这也是为了防止网络偶然抖动导致服务节点流量的大幅波动。

2.3 降权法

上面提到客户端会为每个节点赋予一个权值,改变权值就可以改变节点的相对流量。如果某个节点出现了一次调用错误,可以对该节点进行降权。如果错误次数过多,降权会降的很快,最终达到一个最小值。之所以不应该降到零,那是为了给节点提供一个恢复的机会。被降权的节点后来只要有一次调用成功,那么 weight 值就应该尽快被还原,这样节点就可以快速恢复为正常节点。

客户端一次调用失败会尝试重试。如果降权太慢,会导致重试次数太多,因为第二次随机挑选节点时还是很有可能再次挑选到失效节点。降权太快也不好,网络抖动会导致节点流量分配的快速抖动,瞬间从正常降到近零,又可以瞬间从近零恢复到正常。

一个简单的策略是权重减半法。错误一次权重减半,连续错误两次权重就降到 1/4,如此直到降到最小值。如果初始权重值是 1024,那么权重值就会逐渐衰减1024=>512=>256=>128=>64=>32=>16=>8=>4=>2=>1。如果节点恢复了,那么调用会成功,权重就可以直接恢复到正常值,也可以通过加倍法逐渐恢复到正常值1=>2=>4=>8=>16=>32=>64=>128=>256=>512=>1024。如果希望恢复的更快一点,可以通过乘 4 法,乘 8 法。

2.4 服务发现

健壮的服务应该是可以支持动态扩容的服务。比如 RPC 服务压力过大,希望通过增加节点的方式来减小单个 RPC 服务的压力。如果使用的是前面的静态 RPC 服务地址列表,那么当节点增加时,我们需要修改客户端的配置重启才能生效。

通过服务发现技术,当 RPC 服务节点增加或减少时,客户端可以动态快速收到服务列表的变更信息,从而可以实时调整连接配置,这样无需重启就可以完成服务的扩容和缩容。

class ServiceDiscovery(object):

    def register_service(self, name, addr):
        pass
        
    def get_services(self, name):
        pass
        
    def on_services_changed(self, name):
        pass

服务发现技术依赖于服务之间的特殊中间节点。这个节点的作用就是接受服务的注册,提供服务的查找,以及服务列表变更的实时通知功能。它一般使用支持高可用的分布式配置数据库作为解决方案,如 zookeeper/etcd 等。

  • 服务注册——服务节点在启动时将自己的服务地址注册到中间节点
  • 服务查找——客户端启动时去中间节点查询服务地址列表
  • 服务变更通知——客户端在中间节点上订阅依赖服务列表的变更事件。当依赖的服务列表变更时,中间节点负责将变更信息实时通知给客户端。

参考:

什么是分布式系统,如何学习分布式系统
浅谈分布式缓存那些事儿
多线程并发常见问题
分布式缓存那些事儿
CAP理论中的P到底是个什么意思?
CAP理论基础(注解)
浅谈分布式缓存那些事儿

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值