大话分布式理论之二——共识算法与一致性的区别

[系列目录]

大话分布式理论之二——共识算法与一致性的区别

大话分布式理论之一——从单体到SOA再到微服务

在我们认知分布式理论时,有两个东西常常混在一起,在我的角度看来,他们应该是两个东西——共识算法与一致性协议。
前者强调共识,即在一个范围内的所有节点,如何在一个确定的提案上达成一个统一的结论。
后者强调多副本(或者叫多节点)上的数据一致。

很经典的一个错误认知就是wikipedia在2019年8月的一个对Paxos的定义中,将其描述为“一致性算法”,这一错误在同年12月被修正:

共识算法

拜占庭将军问题

要清晰的认知什么是共识算法,我们需要了解一个广为传播的问题——拜占庭将军问题。

一组拜占庭将军分别各率领一支军队共同围困一座城市。为了简化问题,将各支军队的行动策略限定为进攻或撤离两种。因为部分军队进攻部分军队撤离可能会造成灾难性后果,因此各位将军必须通过投票来达成一致策略,即所有军队一起进攻或所有军队一起撤离。因为各位将军分处城市不同方向,他们只能通过信使互相联系。在投票过程中每位将军都将自己投票给进攻还是撤退的信息通过信使分别通知其他所有将军,这样一来每位将军根据自己的投票和其他所有将军送来的信息就可以知道共同的投票结果而决定行动策略。

共识统一:只要每位将军的消息能够正确的到达其他将军那里,产生多数/少数的情况下,必将产生一个统一的共识。
破坏共识

  • 叛徒将军,叛徒将军刻意谎报,每次拿到其他人的结果之后投票或弃权,导致票数五五开无法达成共识。
  • 叛徒信使或信使被拦截:同样会导致一样的情况,甚至可能让将军们产生截然不同的认知,产生行动的分裂——向提议进攻的将军的将军们送去的信全篡改成进攻,向提议撤离的将军的将军们送去的信全篡改成撤离。
  • 将军数量为偶数: 偶数情况下,可能产生五五开的局面。当然可以再次发起投票,但是也可能再次出现五五开。

分布式理论中的将军们

对于计算机分布式理论中,其实也存在着类似的场景,比如说区块链,比如在具体的应用中,我们部署服务的多个副本应用时需要产生一个主节点。

  • 有同学可能会问,要产生主节点的话,直接用redis锁/zookeeper来存储主节点标识不就可以了吗?

当然可以,但是这里的前提是引入了三方协调者节点,如果不引入,单靠我们自己的一些应用节点该如何实现呢?

此时共识算法就发挥作用了,一套完善的共识算法,可以帮助我们在集群启动时选举一个leader,并且在这个leader宕机的时候,还能重新选举一个leader上来。

这里我们要强调一下,相较于拜占庭将军问题,企业级分布式应用不需要考虑上面的叛徒将军(叛徒节点)和叛徒信使(信道劫持)问题,因为分布式应用之间的通信一般都是隔离网络(内网),网络安全的事情可以交个安全部门去考虑。
当然我们也可以简单思考一下,如果我们的应用是在公网上,该如何防止?区块链就是这样的场景,而他们的做法一般都是建立一套经济模型+POW等机制来预防这样的事情发生。

共识算法-Paxos/Raft等

Leslie Lamport是拜占庭将军问题的提出者,Paxos则是他提出的一种共识算法,可以应用在分布式系统中。
具体的算法内容有兴趣可以再研究,我们这里之分析这些算法的作用。
Paxos Wikipedia:https://zh.wikipedia.org/wiki/Paxos%E7%AE%97%E6%B3%95

  • Paxos
    多个副本节点对一个提案达成一个统一的结果,比如多副本节点的选主。
  • Multi-Paxos
    由于Paxos每次流程只能支持一个提案的达成,效率较低,于是又出现了Muti-Paxos,支持一次协调达成一揽子的提案。
  • Raft
    Raft是对Muti-Paxos的精简,强调易理解、易实现。
  • Multi-Raft
    当下很多分布式数据库存在分片,不同分片之间的数据/信息应该是隔离的,于是需要多个Raft来支持分片,每个Raft对应一个分片,这就是Multi-Raft。
  • ZAB
    ZAB也是对Multi-Paxos算法的改进,是Zookeeper中的选主机制,比Raft协议出现的更早。

共识算法能解决一切共识问题吗?

显然是不可以的。

  • 最大的问题就是脑裂
    什么是脑裂?

    副本节点之间的网络短时间产生隔离,那就很可能产生两/多个leader,当网络恢复正常时,两个leader都保留了下来,产生混乱。

此时只能通过 一些标准来决定谁留下,谁下去

  • 另外一个问题是偶数节点
    在拜占庭将军冢也提到了偶数节点问题,也是因为这个原因,我们在一些zookeeper类似的情况中,官网往往会推荐我们配置的节点数为奇数,以此防止选举不成功-重复选举的情况发生。

了解了什么是共识算法,我们再来聊一聊什么是分布式理论中的一致性。

分布式理论中的一致性

一致性的概念来自CAP理论的定义,其中的C就是一致性:

在理论计算机科学中,CAP定理(CAP theorem),又被称作布鲁尔定理(Brewer’s theorem),它指出对于一个分布式计算系统来说,不可能同时满足以下三点:

  • 一致性(Consistency) (等同于所有节点访问同一份最新的数据副本)
  • 可用性(Availability)(每次请求都能获取到非错的响应——但是不保证获取的数据为最新数据)
  • 分区容错性(Partition tolerance)(以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。)

今天我们只看一致性:

副本节点间的一致性(分布式一致性)

一个分布式集群需要对外部提供强一致性,即集群内部某一台节点的数据发生了改变,必须要所有节点都同步到这个改变之后,外界才能访问集群获取数据。

我们简单了解了什么是强一致性,那么现在我们常说的最终一致性又是什么?

最终一致性:
最终一致性属于弱一致性。

弱一致性:在数据发生变化之后,节点间的数据会逐步趋向于一致。
最终一致性:在数据发生变化时,一段时间后,节点间的数据会最终达到一致状态。

而最终一致性的语义放到今天我们的实践环境中,往往代表的是不要求实时节点数据一致,但要求尽量短的时间窗口内达到数据一致。

最终一致性的方案往往由可靠的异步化完成。

案例-kafka中的一致性

kafka是一个具有主从结构(多副本节点)的分布式消息队列,多副本,就意味着存在一致性问题,那么kafka是如何来实现强一致性与弱一致性的?
其中一个可配置参数是min.insync.replicas,表示 最少的in-sync的节点数

只有所有in-sync的节点都提交了,消息才算提交了。这个数值如果我们配置为全部节点数,那么显然这将是一个强一致性的配置,而如果我们配置的不是全部节点数,那么他就是弱一致性的配置,因为一次数据变更操作完成后,并不能保证每个副本拿到的数据一致。
这也是为什么CAP中的C和A只能选择其一,数据一致性越强,需要同步的副本节点就越多(越全),耗时自然长,那么可对外系统服务的时间就相对缩短了。

应用服务间的一致性(分布式事务一致性)

应用服务中的最终一致性又有所不同,应用服务中的一致性往往谈的是分布式事务中的一致性,与数据库事务的ACID中的C是一样的。
强调一个事务过程中,服务A产生的数据变更,对应的服务B也要做出符合逻辑的数据变更,这个因果关系是一定的。

以具体的业务举例,一个下单流程中,支付服务成功收款,那么库存系统必须减少相应的库存,这就是分布式事务中的一致性。
而分布式事务最终一致性,同样也是对一致性的时间限制放松,只要在一定时间内,最终的数据能够满足一致性即可。

分布式事务的强一致性实现方案
2PC(二阶段提交):

2PC存在一些广为人知的问题,比如协调者和参与者宕机的case,于是出现了3PC,有兴趣的同学可以深入了解。

在数据库领域,2PC的实现叫做XA事务。当然今天的分布式数据库基本上都是采取了其他的方案而非XA,这是后话。
而在应用服务领域,应用2PC这些理论,产生了一些分布式事务的框架,比如Seata提供的XA/AT/TCC模式其实都有2PC的影子在里面。

案例2-应用系统中的最终一致性

应用系统中的最终一致性同样依赖可靠的异步化来实现。
以下单为例,在事务发生的时候不去扣减库存,而是在事务结束之后,借用消息等方式实现库存的异步化扣减。
当然,这样做的前提是这个业务系统中,库存的扣减没有对下单的动作的逻辑限制。

那么消息又如何保证可靠呢?怎么保证一定不丢失呢?
关于这个问题,可以参考ebay曾经提出的一种解决方案——MQ中间件+本地消息表方案。
或者 RocketMq的事务消息等。


欢迎关注微信公众号 【JAVA技术分享官】,公众号首发,持续输出原创高质量JAVA开发者知识点

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值