一致性(consistency)
说到一致性,我们可能最先想到的数据库里的事务
这里的讨论的是分布式的一致性,事务就简化一下,只考虑Read/Write
先列举一下事务的种类:
-
单机的事务:多个复杂事务发生在一个节点上
-
分布式的事务a:多个简单事务发生在多个节点上,一个事务只涉及一个节点
-
分布式的事务b:多个复杂事务发生在多个节点上,一个事务可能涉及多个节点
这里就考虑2了
参考资料:
http://kaiyuan.me/2018/04/21/consistency-concept/
https://www.codedump.info/post/20220710-weekly-22/
http://zhangtielei.com/posts/blog-distributed-causal-consistency.html
https://qiankunli.github.io/2022/04/06/replica_consistency_level.html
线性一致性(强一致性)
整个系统表现的像一台单机:
- 只要写成功,所有节点都能读到最新的数据
- 对所有client而言,仿佛所有操作都是按照实际时间的先后串行化的
怎么实现强一致性?
- 写的时候必须等所有节点都同步好了才返回
- 读的时候slave去问master要数据
理想的情况:操作的时间域不重叠(P1,P2表示2个发送请求的客户端)
区间->点:操作成功的时刻就在线段的一个点上,所以我们可以将上图抽象为下面的样子,可以发现系统满足线性一致性(举个反例:如果Read读出来的是2,就不满足了)
实际的情况:操作的时间域有重叠,但是没关系,因为操作真正成功可以理解为成时间线段里面的一个时间点
也就是说,操作的顺序不是按照提交时的时间来算的,只要时间段有重叠,那么谁先谁后都有可能:比如说下面的情况,可能是W2先完成,也可能是W3先完成
例子1:我们来看看下面这个系统是否满足线性一致性:
可以的:
例子2:不满足线性一致性的情况:不管我们怎么调整Write2和Write3的顺序,也不可能让后面的Read操作读出2个不同的值
顺序一致性
只要保证同一个节点内的操作是按序的即可,节点之间的操作顺序可以随便编排
顺序一致性可以理解成一个特殊的因果一致性:同一个节点内的一系列操作中,前后有因果关系
通俗地讲,虽然你9点吃了饭,但是并不一定能及时的传播到我这边,所以我感知到你吃了饭时,可能已经12点了
但是我观察到的你的事件顺序,必须是跟你真实的情况一致的,我不能先看到你吃中饭,再吃早饭
用这个不满足线性一致性的例子:
重新编排后可以发现满足顺序一致性
因果一致性
概括:我不能还没看到你的贴子,就先看到评论了
个人认为因果一致性跟顺序一致性是两个维度的
因果不一定满足顺序:虽然你先吃饭再睡觉,但是我可以观察到你先睡觉再吃饭(只要你的吃饭&睡觉只有时间上的先后,没有因果关系)
顺序不一定满足因果:A在大喊一声导致B醒了,但是C可以观察到B先醒了,然后A大喊一声
举个没有保持因果关系例子:
- A发了动态1:东西丢了,真倒霉
- A发了动态2:东西找到了,真好
- B看到了动态1
- B看到了动态2
- B对A发表评论1:恭喜
- C看到了动态1
- C看到了评价1,觉得B太损人了(在这步时因果已经出问题了)
- C看到了动态2,发现误会了
画成图,大致如下:
所有的因果关系罗列一下(不考虑8):
A的因果关系:W1 -> W2
B的因果关系:R1 -> R2 -> W6
C的因果关系:
A和B之间的因果关系有:W2 -> R2, W1 -> R1
B和C之间的因果关系有:W6 -> R6
A和C之间也有因果关系:W1 -> R1
你会发现,刚到第7步时,虽然因果关系图还是没有产生环的,但是此时因果已经出问题了(产生误会了)
所以为了保证因果一致性,必须:当我看到别人的果时,我必须要看到该果之前的所有因;而不是傻傻地检测新的事件会不会造成环
最终一致性
最终总能到达一个完全一致的阶段,大家手里的数据都是一样的