在分布式复制中提到了多个从节点的复制下的数据一致性。

比如多个从节点,数据不是一致的,那么对于客户端就会产生读不一致的情况。

虽然可以保证最终一致性,但是在可用性上还是很低的, 属于弱一致性的范畴。

所以分布式一致性在于,面对延迟和故障的时候,如何协调副本间的状态。

强一致性

也称为:原子一致性(Atomic Consistency)| 线性一致性(Linearizable Consistency)

线性一致性的目的就是让每一个从节点的数据都是一致的,看起来就是只有一个从节点的状态。

简言之,在任意时刻,所有节点中的数据是一样的。例如,对于关系型数据库,要求更新过的数据能被后续的访问都能看到,这是强一致性。

顺序一致性(Sequential Consistency)

两个要求:

  1. 任何一次读都能读到某个数据的最近一次写的数据。
  2. 系统的所有进程的顺序一致,而且是合理的。即不需要和全局时钟下的顺序一致,错的话一起错,对的话一起对。

顺序一致性可以认为是一个线程开始的时候做一个系统快照,只关心自己线程的数据,不关心快照之后,其他线程如何更新数据

  1. 图a是满足顺序一致性,但是不满足强一致性的。原因在于,从全局时钟的观点来看,P2进程对变量X的读操作在P1进程对变量X的写操作之后,然而读出来的却是旧的数据。但是这个图却是满足顺序一致性的,因为两个进程P1,P2的一致性并没有冲突。从这两个进程的角度来看,顺序应该是这样的:Write(y,2) , Read(x,0) , Write(x,4), Read(y,2),每个进程内部的读写顺序都是合理的,但是这个顺序与全局时钟下看到的顺序并不一样。
  2. 图b满足强一致性,因为每个读操作都读到了该变量的最新写的结果,同时两个进程看到的操作顺序与全局时钟的顺序一样,都是Write(y,2) , Read(x,4) , Write(x,4), Read(y,2)。
  3. 图c不满足顺序一致性,当然也就不满足强一致性了。因为从进程P1的角度看,它对变量Y的读操作返回了结果0。那么就是说,P1进程的对变量Y的读操作在P2进程对变量Y的写操作之前,这意味着它认为的顺序是这样的:write(x,4) , Read(y,0) , Write(y,2), Read(x,0),显然这个顺序又是不能被满足的,因为最后一个对变量x的读操作读出来也是旧的数据。因此这个顺序是有冲突的,不满足顺序一致性。

但是对于部分的场景,线性一致性是必须的:

  • 锁定和选举领导
  • 约束和唯一性保证 - 银行余额的保证
  • 跨信道的时序依赖 - 消息队列和数据库数据的一致性保证必须要是线性的

那么当前对线性一致性的实现情况如何呢?

  • 单主复制:可能线性一致 , 如果从主库和同步更新的从库获取数据就是线性一致的
  • 共识算法加持:安全实现一致性存储
  • 多主复制: 无法做到线性一致,都节点同时写入,异步复制如何保证? 不可能的
  • 无主复制:面对时钟的不确定性和网络延时,可能不是线性一致的

还有一个点就是线性一致的性能问题 , 所以在允许低延迟的业务场景小,适当调整比较合理。

弱一致性

数据更新后,如果能容忍后续的访问只能访问到部分或者全部访问不到,则是弱一致性。

最终一致性

不保证在任意时刻任意节点上的同一份数据都是相同的,但是随着时间的迁移,不同节点上的同一份数据总是在向趋同的方向变化。

简单说,就是在一段时间后,节点间的数据会最终达到一致状态。

共识

共识问题中所有的节点要最终达成共识,由于最终目标是所有节点都要达成一致,所以根本不存在一致性强弱之分。

例如,Paxos是共识(Consensus)算法而不是强一致性(Consistency)协议。共识算法没有一致性级别的区分。

关联阅读:

缓存一致性

  • 复习 分布式系统一致性和共识 (@2023-12-12)