Consistency
一致性
一致性模型有很多,如
- 线性一致性
- 顺序一致性
- 因果一致性
- 最终一致性
等等。
线性一致性
线性一致性一开始是在并发领域提出的。
并发角度
一致性模型是指,在并发编程中,系统和开发者之间的一种约定。如果开发者遵循某种规则,那么开发者执行读操作或者写操作的结果是可预测的。
重点落在可预测的,可预测保证了程序逻辑的确定性。这么说起来很抽象,
在我看来,从并发角度,线性一致性避免了data race的问题,让读写操作串行化。
在每次读操作时,都能看到最新的写操作的结果。
分布式角度
非严格定义:线性一致性保证分布式系统的所有操作都像原子操作,且分布式系统看起来仅仅只有一个节点。
严格定义:给点一个执行历史,根据并发操作可以扩展成多个执行序列,只要从中找出一个符合现实观察的历史,那就是线性一致的。
在我看来,一致性算是程序给用户的对于执行顺序某种保证。
比如,线性一致性保证了用户请求按照请求时间顺序执行,不同用户的命令执行顺序根据全局时间排序来执行,当然并发关系的操作的执行顺序就看程序怎么安排,这是无法保证的。
而顺序一致性只保证了一个用户的所有请求的执行顺序,而不同用户之间的请求顺序是无法保证的,可能用户
A先请求,B后请求,但用户B的请求先执行。
例子
拿Raft算法举例,Raft论文中提到的最基本Raft实现(读写都是log)就是线性一致性的。
所有用户的请求,不论读写,都是在leader上请求,这就保证了后续的读一定是更新的结果。
可能你会说,leader也是会更换的呀?不同的server的日志是不同呀的?
Raft算法保证了,只有apply了的的请求才能做出回应,而apply <= commit, commit了的log就一定复制到了大多数server上,就保证了就算leader变更,新leader也保留有新日志。
由于读写都是log,都需要commit后才回复,因此不论读写,Raft都保证了线性一致性。
但对于部分Raft读改进版来说,写是线性一致性写,但读不是。
写是需要改变状态机的状态的,因此写操作仍是需要apply的,但读操作不是,读并不改变状态机的状态,无需经过提交也很合理,同时也为了减轻leader的负担,Raft改进版就可以从读下手。
让其他server直接返回读的结果,无须经过leader来操作,对于任意一个server,只有他的log跟leader保持最新,他才可以说是线性一致性的。否则,读到的就不是最新的结果。就无法保证线性一致性,甚至是顺序一致性。