什么是分布式一致性
分布式数据一致性,指的是数据在多份副本中存储时,各副本中的数据是一致的。
副本一致性
分布式系统当中,数据往往会有多个副本。如果是一台数据库处理所有的数据请求,那么通过ACID四原则,基本 可以保证数据的一致性。而多个副本就需要保证数据会有多份拷贝。这就带来了同步的问题,因为我们几乎没有办 法保证可以同时更新所有机器当中的包括备份所有数据。 网络延迟,即使我在同一时间给所有机器发送了更新数据 的请求,也不能保证这些请求被响应的时间保持一致存在时间差,就会存在某些机器之间的数据不一致的情况。
总得来说,我们无法找到一种能够满足分布式系统所有系统属性的分布式一致性解决方案。因此,如何既保证数据 的一致性,同时又不影响系统运行的性能,是每一个分布式系统都需要重点考虑和权衡的。于是,一致性级别由此 诞生:
一致性分类
- 强一致性
这种一致性级别是最符合用户直觉的,它要求系统写入什么,读出来的也会是什么,用户体验好,但实现起来往往 对系统的性能影响大。但是强一致性很难实现。 - 弱一致性
这种一致性级别约束了系统在写入成功后,不承诺立即可以读到写入的值,也不承诺多久之后数据能够达到一致,但会尽可能地保证到某个时间级别(比如秒级别)后,数据能够达到一致状态。主要有以下几种
- 读写一致性
用户读取自己写入结果的一致性,保证用户永远能够第一时间看到自己更新的内容。 比如我们发一条朋友圈,朋友圈的内容是不是第一时间被朋友看见不重要,但是一定要显示在自己的列表上.
解决方案:
1.一种方案是对于一些特定的内容我们每次都去主库读取。 (问题主库压力大)
2.我们设置一个更新时间窗口,在刚刚更新的一段时间内,我们默认都从主库读取,过了这个窗口之后,我们会挑 选最近有过更新的从库进行读取
3.我们直接记录用户更新的时间戳,在请求的时候把这个时间戳带上,凡是最后更新时间小于这个时间戳的从库都 不予以响应。
- 单调读一致性
本次读到的数据不能比上次读到的旧。 由于主从节点更新数据的时间不一致,导致用户在不停地刷新的时候,有时候能刷出来,再次刷新之后会发现数据不见 了,再刷新又可能再刷出来,就好像遇见灵异事件一样
解决方案:就是根据用户ID计算一个hash值,再通过hash值映射到机器。同一个用户不管怎么刷新,都只会被映射到同 一台机器上。这样就保证了不会读到其他从库的内容,带来用户体验不好的影响。
- 因果一致性
指的是:如果节点 A 在更新完某个数据后通知了节点 B,那么节点 B 之后对该数据的访问和修改都是基于 A 更新后 的值。于此同时,和节点 A 无因果关系的节点 C 的数据访问则没有这样的限制。
- 最终一致性
最终一致性是所有分布式一致性模型当中最弱的。可以认为是没有任何优化的“最”弱一致性,它的意思是说,我不考虑 所有的中间状态的影响,只保证当没有新的更新之后,经过一段时间之后,最终系统内所有副本的数据是正确的。 它最大程度上保证了系统的并发能力,也因此,在高并发的场景下,它也是使用最广的一致性模型。