2021-2-16:请问你知道分布式设计模式中的Quorum思想么?

有效个数(Quorum)

有效个数(Quorum)这个设计模式通常是指分布式系统的每一次修改都要在大多数实例上经过来肯定修改经过。mongodb

问题背景

在一个分布式存储系统中,用户请求会发到一个实例上。一般在一个实例上面执行的修改,须要复制到其余的实例上,这样能够保证在原实例挂了的状况下,用户依然能够看到这个修改。这就涉及到一个问题,究竟复制到多少个其余实例上以后,用户请求才会返回成功呢?若是复制的实例个数过多,那么请求响应时间就会更长;若是复制的实例过少,则这个修改可能会丢失。取得这个平衡性很重要,这也是分布式 PACELC 中的 L(Latency) 与 C(Consistency) 的取舍。编程

解决方案

当一个修改,被集群中的大部分节点(假设个数为N)经过以后,这个修改也就被这个集群所接受。这个 N 就是有效个数。假设集群数量为 n,那么 N = n/2 + 1.例如 n = 5,则 N = 3.设计模式

这个有效个数,间接地体现了集群中最多能够有多少个实例挂掉,这个数量就是 f = n - N。一般的,若是咱们指望能够忍受 f 个实例挂掉,那么集群就至少要有 2f + 1 个实例。微信

如下就是两个经典须要有效个数这个设计模式的场景:并发

  • 更新存储集群中的数据。同时还会涉及到最高水位线(High-Water Mark)这个设计模式,用于标注截止到哪里的日志,已经同步到了集群中的大多数实例。
  • 选主。在主从(Leader and)设计模式中,被有效个数选举为主的就是最终的主。

如何设计集群个数

目前主流的集群设计模式有以下两种:异步

image

  • 第一种是主从同步模式:
    • 一种是请求发往主,主负责同步到其余从上面,以后返回。若是请求发到了从上面,则从发到主上面处理。例如 Zookeeper 就是这么作的。
    • 另外一种是,请求发到哪一个实例,哪一个实例就是主,主将请求同步到从上面。例如 Eureka 就是这么设计的。
  • 第二种是分区模式,集群中不一样节点存储不一样数据。通常的,这个数据切分常常采用一致性哈希。假设请求发送到了 A,通过 A 的计算,这个数据须要存储在 D,而且咱们配置的存储备份是一份,这个备份是在 E 上面,这样这个请求就会被同步到 D,E 上面。ElasticSearch,Riak,Dynamo 就是这种相似的设计。

在这种设计模式下的系统,主要考虑两点:分布式

  • 写操做的吞吐量。由于每次写入集群,都要复制到多个实例,因此确定会对性能有所影响。通常的,复制是并发复制的,这个性能主要受本次同步最慢的那个实例的影响。
  • 能够容忍的实例挂掉的个数。这样的集群,若是咱们指望能够忍受 f 个实例挂掉,那么集群就至少要有 2f + 1 个实例。

实现举例

1. Zookeeper 的两阶段提交 + 半数以上写入机制

客户端把写请求发送到 leader 节点上(若是发送的是 follower 节点,follower节点会把写请求转发到leader节点),leader节点会把数据经过proposal请求发送到全部节点(包括本身),全部到节点接受到数据之后都会写到本身到本地磁盘上面,写好了之后会发送一个ack请求给leader,leader只要接受到过半的节点发送ack响应回来,就会发送commit消息给各个节点,各个节点就会把消息放入到内存中(放内存是为了保证高性能),该消息就会用户可见了。函数

2. Riak,DynamoDB

默认状况下,是 P+A 以及 E+L 的系统,可是能够根据配置修改,主要基于NWR模型与同步和异步备份。N 表明 N 个备份,W 表明要写入至少 W 份才认为成功,R 表示至少读取 R 个备份。配置的时候要求 W+R > N。 由于 W+R > N, 因此 R > N-W。这个是什么意思呢?就是读取的份数必定要比总备份数减去确保写成功的倍数的差值要大。
也就是说,每次读取,都至少读取到一个最新的版本。从而不会读到一份旧数据。当咱们须要高可写的环境的时候(例如,amazon 的购物车的添加请求应该是永远不被拒绝的)咱们能够配置W = 1 若是N=3 那么R = 3。 这个时候只要写任何节点成功就认为成功,可是读的时候必须从全部的节点都读出数据。若是咱们要求读的高效率,咱们能够配置 W=N R=1。这个时候任何一个节点读成功就认为成功,可是写的时候必须写全部三个节点成功才认为成功。
你们注意,一个操做的耗时是几个并行操做中最慢一个的耗时。好比R=3的时候,其实是向三个节点同时发了读请求,要三个节点都返回结果才能认为成功。假设某个节点的响应很慢,它就会严重拖累一个读操做的响应速度性能

3. MongoDB

MongoDB 和上面的 Dynamo 相似,MongoDB关于一致性、可用性的权衡,取决于三者:设计

  • write-concern: 表示当写请求在value个MongoDB实例处理以后才向客户端返回
  • read-concern: 设定是否必须从 primary 读取最新的数据仍是能够从 secondary 读取最终一致性的数据。
  • read-preference: 对于replica set,是返回当前节点的最新数据,仍是返回写入节点最多的数据,仍是根据一些函数计算出的数据。

微信搜索“个人编程喵”关注公众号,每日一刷,轻松提高技术,斩获各类offer:

image

相关文章
相关标签/搜索