架构设计事务篇之CAP定理

avatar

概述

CAP定理其名称源自这三个单词的首字母, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性)。要理解CAP到底说的是什么,那我们的先明确三个单词的确切含义。

分区容错性

在一个分布式的系统中,一般情况下节点之间的通信是正常的,但是当出现网络异常时造成节点之间无法彼此通信时,此时该系统会被异常的网络划分成好几个独立的区,
区内的节点可能可以彼此通信但区与区却不行,这便是分区现象,但是当网络从异常中恢复时分区现象也便会消失,节点之间的通信也会恢复到正常状态。

假如你的数据在系统中只有一份,那么当系统出现分区时,恰好该数据位于因网络异常处于分区状态的节点上,此时便无法对该数据进行读写,那么我们就可以说该分布式系统没分区容忍性。
如果要让系统具备分区容忍性,那么我们可以让分布式系统中的每个节点都存储一份该数据,当某个节点因分区无法访问时,可以访问其它网络正常的节点来获取数据,此时我们就说该分布式系统具有分区容忍性。

因此,一般分布式的系统都要支持分区容忍性,所以CAP中的P在分布式的系统中是必须要实现的一个特性,实现的方式是使用副本机制。

一致性

这里的一致性和数据库所说的一致性是有差异的,这里指的是在多副本的分布式数据系统中,向任意节点写入成功的数据和写之后从任意节点读取的数据,两者是一样的,也就是向任意节点发起写操作之后,其它节点的数据和该节点的数据是完全一致的状态。
比如,在一个有三个节点的分布式数据系统中,有一数据项A,它有三个副本分别位于三个节点上;
此时如果向三个节点中的任意节点发起写操作将A修改为1,修改成功后,立即从任意节点读取A的数据值,如果A的值等于1那么我们就说该系统具有一致性。

但是,当系统出现分区时,如果我们不采取任何措施,那么是无法保障数据的一致性的。
比如,刚开始数据A在节点1、节点2上的值为1,当节点1、节点2不同通信出现分区现象时,此时有一个用户向节点1发起修改A数据为2的请求,有另一个用户向节点2发起修改A数据为3的请求;
此刻如果允许两个用户的写入操作,那么势必造成A数据在节点1为2,在节点2为3不一致的情况,如何解决?

可用性

上面的例子,如果你选择在出现分区的时候允许各节点继续提供写服务,哪怕会发生数据不一致情况,那么你选择的就是可用性。
所以,可以看出当可用性优先时,数据一致性就得不到保障。

取舍

如上,如果出现分区我们选择可用性,那么就会以牺牲可用性为代价,但是这不意味我们放弃了一致性。
我们仍然可以尽可能的通过一些预防或补救措施来避免分区发生时数据的不一致。
比如,当系统探测到分区现象发生时,如果条件允许那么可以通过选举机制剔除异常的节点;
再如,当数据出现不一致时,可以按时间顺序对不一致的数据进行合并,当然合并可能也会像Git一样出现数据冲突的情况。
无论怎么说,大部分的分布式系统在A和C之间,一般都以可用性优先,然后尽可能的保障数据的一致性,如著名的BASE理论。

BASE

BASE理论是对以可用性优先的AP系统最好的补充理论,它强调如果我们无法保障数据的强一致性(在时间上表现为试试一致),那么我们可以通过事后的补救措施来实现数据最终的一致。
基于消息中间件实现数据的最终一致是BASE理论的一个应用实列,相较于2PC(两阶段事务)、3PC(三阶段事务)以及TCC来说,它不能实时保障数据一致,但可以在一定的期限内最终保障数据一致,而其它的一致性算法都有可能因为分区导致事务失败的可能。

扩展阅读

架构设计思维篇之结构

架构设计思维篇之概念

架构设计容错篇之重试

架构设计容错篇之熔断

架构设计容错篇之限流

架构设计事务篇之Mysql事务原理

架构设计事务篇之CAP定理

架构设计事务篇之分布式事务

架构设计消息篇之消息丢失

架构设计消息篇之保证消息顺序性

推荐阅读更多精彩内容