最终一致性
牺牲一致性,只是不再要求关系型数据库中的强一致性,而是只要系统能达到最终一致性即可
考虑到客户体验,这个最终一致的时间窗口,要尽可能的对用户透明,也就是需要保障“用户感知到的一致性”。
通常是通过数据的多份异步复制来实现系统的高可用和数据的最终一致性的,“用户感知到的一致性”的时间窗口则取决于数据复制到一致状态的时间。
一致性是因为有并发读写才有的问题
对于关系型数据库,要求更新过的数据能被后续的访问都能看到,这是强一致性。如果能容忍后续的部分或者全部访问不到,则是弱一致性。如果经过一段时间后要求能访问到更新后的数据,则是最终一致性。
- N — 数据复制的份数
- W — 更新数据是需要保证写完成的节点数
- R — 读取数据的时候需要读取的节点数
最终一致性举例:
我要从3个节点上读数据(R=3),但是该数据库2个或者1个写入,就算写入成功(W<3),但是这个数据库的备份数量是3或者4(N>=3)
此时一份数据已经写入成功了,但是没有备份成功,
此时读数据的请求不能达成,要等待备份数量达到R的数量,该读请求才能完成,
此刻进入等待,这就是最终一致性。
假设我有一份数据,备份在3台机器上。
我更新数据的时候更新w台机器的数据就算成功,(w在1-3之间)
我读数据的时候我在r台机器上读数据(r也在1-3之间)
那么,只要我写的机器和读的机器必定有重叠的,就是强一致性。即w+r>3, 比如我数据更新在2台机器上,然后我在任意2台机器上读,那必定有一台机器是最新数据。
如果它们可能没有重叠,就是弱一致性。即w+r<=3. 比如我更新在2台机器上,我只要在一台机器上读就可以,那我有可能在那台旧数据的机器上读数据。
最终一致性就是弱一致性,只不过,增加了"多个异步操作"。
如上个例子,我更新了2台机器的数据,但是我的备份是3台,那我第三台机器由于我的异步复制系统,最终肯定会有最新的数据的。那么在异步复制完成前,我可能读到旧的数据,完成后我就不会读到旧数据了,数据最终会保持一致。
举例2:hdfs就是最终一致性。 hdfs写入的时候,只要一个数据块写入就算成功。读取的时候也只要从一台节点上读取数据。但是hdfs的默认备份是3份。
因为hdfs有异步数据复制的机制
--------------------------------------------------------------------------------------------------------
以下为摘抄:
上述最终一致性的不同方式可以进行组合,例如单调读一致性和读己之所写一致性就可以组合实现。并且从实践的角度来看,这两者的组合,读取自己更新的数据,和一旦读取到最新的版本不会再读取旧版本,对于此架构上的程序开发来说,会少很多额外的烦恼。
从服务端角度,如何尽快将更新后的数据分布到整个系统,降低达到最终一致性的时间窗口,是提高系统的可用度和用户体验非常重要的方面。对于分布式数据系统:
- N — 数据复制的份数
- W — 更新数据是需要保证写完成的节点数
- R — 读取数据的时候需要读取的节点数
如果W+R>N,写的节点和读的节点重叠,则是强一致性。例如对于典型的一主一备同步复制的关系型数据库,N=2,W=2,R=1,则不管读的是主库还是备库的数据,都是一致的。
如果W+R<=N,则是弱一致性。例如对于一主一备异步复制的关系型数据库,N=2,W=1,R=1,则如果读的是备库,就可能无法读取主库已经更新过的数据,所以是弱一致性。
对于分布式系统,为了保证高可用性,一般设置N>=3。不同的N,W,R组合,是在可用性和一致性之间取一个平衡,以适应不同的应用场景。
- 如果N=W,R=1,任何一个写节点失效,都会导致写失败,因此可用性会降低,但是由于数据分布的N个节点是同步写入的,因此可以保证强一致性。
- 如果N=R,W=1,只需要一个节点写入成功即可,写性能和可用性都比较高。但是读取其他节点的进程可能不能获取更新后的数据,因此是弱一致性。这种情况下,如果W<(N+1)/2,并且写入的节点不重叠的话,则会存在写冲突
浙公网安备 33010602011771号