专栏首页企鹅号快讯分布式系统一致性分类,你知道几种?

分布式系统一致性分类,你知道几种?

为了提升系统的可用性、性能、扩展性,我们可以从两个方面着手,

要去建立多个副本。可以放到不同的物理机、机架、机房、地域。一个副本的失效可以让请求转到其他副本。

对数据进行分区。复制多个副本解决了读的性能问题,但是无法解决写的性能问题。根据关键字进行分片,实现数据分布式,进一步提升系统的写性能。

以上两种方式最复杂的问题就是如何保证一致性。一致性问题一直以来都是分布式系统的痛点,因为本身一致性的场景有很多,并不是所有的系统都要求是强一致的,强一致需要极大的成本,我们需要根据系统的容忍度适当放宽一致性的要求。

在很多人看来,银行间转账应该是强一致的,但是你仔细分析一下会发现,小王给小张转账1000元,小王的账户扣除了1000,此时小张并不一定会收到1000元,可能会存在一个不一致的时间窗口。也就是小王的钱扣除了1000元,小张还没收到1000元。另外一个例子,在12306网站买票的功能,也未必是强一致的,如果你在12306上发现一张票还剩余10张,发起请求订了一张票,系统给你返回的可能是“正在排队,剩余10张票,现在有15人在购买”,可能需要你去查询未完成订单,并没有给你及时返回成功或失败的结果。如果有人退了一张票,也没有立即返回到票池中。这里明显也存在不一致的时间窗口。

学术界的一致性模型主要从两个角度去分类:

以数据为中心的一致性模型;

以客户为中心的一致性模型。

以数据为中心的一致性模型

以数据为中心的一致性是从数据存储的角度出发的,包括数据库、文件等。

如上图所示,实际上,一致性是进程和数据之间的规则约定。在下面的示例中,我们假设有多个进程,用p来表示,跟进程对应的有多份存储,a来表示变量,W(a)1来表示进程写入a=1,R(a)1表示读取a的值,结果为1。

以下一致性模型是异步执行的,没有任何同步操作。

a.严格一致性(Strict Consistency)

严格一致性要求任何写操作都能立刻同步到其他所有进程,任何读操作都能读取到最新的修改。要实现这一点,要求存在一个全局时钟,但是,在分布式场景下很难做到,所以严格一致性在实际生产环境中目前无法实现。

如上图,所有的对变量a的读取都能够读取到最新的值,无论是否在一个进程上。

问题:全局时钟难以实现。

b.顺序一致性(Sequential Consistency)

既然全局时钟导致严格一致性很难实现,顺序一致性放弃了全局时钟的约束,改为分布式逻辑时钟实现。顺序一致性是指所有的进程以相同的顺序看到所有的修改。读操作未必能及时得到此前其他进程对同一数据的写更新。但是每个进程读到的该数据的不同值的顺序是一致的。

(一)满足顺序一致性(二)不满足顺序一致性

如图(一)所示,对于变量a的写操作发生在三个不同的进程,如果按照严格一致性,变量a的结果应该是3,在顺序一致性的场景下,有一个确定顺序的过程,由于没有全局时钟,后执行的进程未必最后到达,可能导致最后a的值是1,只要三个进程读取到的顺序是一致的,哪怕最后一次读取到的是1,也是满足顺序一致性的。 但是图(二)非常明显的,三个进程读取出来的顺序是不一致的,p2读取到的结果顺序和p1、p3不同,不能满足顺序一致性。

顺序一致性需要额外实现一个逻辑时钟服务,有额外的性能开销。

c.因果一致性(Causal Consistency)

因果关系是指Lamport在分布式时钟事件序论文中描述的happen-before关系及其传递闭包。因果一致性是一种弱化的顺序一致性。所有进程必须以相同的顺序看到具有潜在因果关系的写操作。不同进程可以以不同的顺序看到并发的写操作。

(一)不满足因果一致性(二)满足因果一致性

如图(一)所示,p2中的读写存在因果关系,W(a)=2可能是先读到了a=1计算后的结果。所以p3中读到的顺序不满足要求,在读到a=2之后,不能再读到a=1。因为图(二)不存在因果关系,所以并不做要求,满足因果一致性。

相比于顺序一致性,因果一致性只强调存在因果关系的操作被看到的顺序一致,没有因果关系的操作被看到的顺序可以不一致。因果一致性并不对并发操作排序,在分布式系统中,如果a和b是并发的,且a和b是两个不相关的操作,没有任何因果关系,那么它们在分布式系统中复制就不必遵循任何顺序了,这样就避免了在它们之间使用因果这种串行化方式。因为串行化会成为系统的性能瓶颈。因果一致性提升了并行的概率。

d.FIFO一致性(FIFO Consistency)

在因果一致性模型上的进一步弱化,FIFO一致性要求所有进程以某个单一进程提出写操作的顺序看到这些写操作,但是不同进程可以以不同的顺序看到不同的进程提出的写操作。通俗来讲,就是要求在一个进程内,所有的写操作必须对外可以被看到的时候,必须是一致的,但是两个进程的写操作的顺序被看到是时候可以不同,是不受保证的,就算是有因果关系也不保证。

(一)满足FIFO一致性(二)不满足FIFO一致性

如图(一)所示,p3在任何时刻读取到的a的值的顺序,只要保证在p1、p2各自的写顺序就可以了,也就是要保证3在1的后面,4在2的后面,哪怕4和3存在因果关系。图(二)的两种情况违背了单进程的写顺序。

FIFO一致性在实际过程中,可以适当变化,根据业务情况把有因果关系的数据放到一个分区,在同一个进程写入。例如某电商价格系统在设置价格时,会写入Kafka,可以根据商品ID分区,在消费阶段,一个分区最多只有一个消费者,在同一个分区Kafka是保证顺序消费的。但是在不同分区没有任何约束。满足业务一致性的前提下,极大的提升了并发处理能力。

以下三个一致性是需要同步变量的。也就是说,当一个进程对变量设置值的时候,不保证其他进程什么时候能够看到值的变化,但是当执行了一次同步操作后,所有进程会看到最新的值。此处不再详细介绍。

a.弱一致性(Weak Consistency)

b.释放一致性(Release Consistency)

c.入口一致性(Entry Consistency)

以用户为中心的一致性模型

在实际业务要求中,很多时候并不要求系统内所有的数据都保持一致,例如在线的日记本,业务只要求基于这一个用户满足一致性即可,不需要关心整体。这就是所谓的以用户为中心的一致性。

以下一致性模型适应的场景为,不会同时发生更新操作,或者同时发生更新操作时,能够比较容易的化解。因为这里的数据更新默认有一个与之关联的所有者,此所有者拥有唯一被允许修改数据的权限,可以按照用户ID进行路由,通过这种方式,可以大概率避免写-写冲突,除非出现重新负载均衡的过程。在读多写少的场景中,例如CDN、CDN,读写比非常悬殊,如果网站的运营人员修改了一张图片,最终用户延迟一段时间看到这个更新实际上问题不大。我们把这种一致性归结为最终一致性。最终一致性是指如果更新的间隔时间比较长,那么所有的副本能够最终达到一致性。

以下示例,我们简化一下场景,假设有一个进程对一份数据的一个副本进行操作,更新要传递给其他副本,注意,这里是一个进程,而前面以数据为中心的一致性模型中的例子是多个进程。

a.单调读一致性(Monotonic-read Consistency)

单调读一致性是指如果一个进程读取数据项a的值,那么该进程对a执行的任何后续读操作总是得到第一次读取的那个值或更新的值。

(一)满足单调读一致性(二)不满足单调读一致性

如图(一),如果变量a的初始值为0,一个进程P在L1副本上做加1操作,得到结果a=1,此时a=1从L1副本传递到L2,进程P又在L2副本做加1操作,但是L2副本中的a并没有立即传递到L1,进程P在L1上读到a仍然是1,然后进程P又在L2上读到a=2,明显比上一次读到的值更新,符合单调读一致性。而图(二)进程P先在L1加1,随后读取a=1,此时变量a的值还没有传递到L2,进程P在L2读到的a=0,读到了更老的版本,显然不符合单调读一致性。

单调读一致性强调任何时刻不能读到比以前读到的数据还旧的数据。实际业务中,某一用户读到了一个审批流程,在页面看到已经进行到了第四步,刷新了一下,可能路由到了另外一个数据副本,又回到了第三步,产生了比较莫名其妙的错误。

b.单调写一致性(Monotonic-write Consistency)

单调写一致性是指一个进程对数据项a执行的写操作必须在该进程对a执行任何后续写操作前完成。

(一)满足单调写一致性(二)不满足单调写一致性

如图(一),如果变量a的初始值为0,一个进程P在L1副本上做加1操作,得到结果a=1,在a=1从L1副本传递到L2之后,进程P又对a做加1操作,此时a=2。满足单调写一致性的要求。图(二)a加1操作并没有及时传递,导致进程P在L2做加1操作时,得到的结果有误。

注意,单调写一致性跟以数据为中心的FIFO一致性类似,但是他们的场景不同,FIFO一致性是多个进程同时去写,而此处强调的是针对一个进程。在实际业务中,例如有一款游戏,用户打怪升级,杀死一个怪物增加100经验值,此时如果不满足单调写一致性,有可能导致用户杀死怪物后,经验值没有增加的问题。

c.写后读一致性(Read-your-writes Consistency)

写后读一致性是指一个进程对数据项a执行一次写操作的结果总是会被该进程对a执行的后续读操作看见。

(一)满足写后读一致性(二)不满足写后读一致性

如图(一),如果变量a的初始值为0,一个进程P在L1副本上做加1操作,得到结果a=1,在a=1从L1副本传递到L2之后,进程P在L2上读到了最新的值,此过程满足写后读一致性。而图(二),读并没有得到最新的结果,导致不满足写后读一致性。

例如一个用户发了一个微博,如果后端mysql采用master-slave结构做读写分离,当并发量比较大时产生了延迟,结果他发完后没有在自己的微博列表看到刚刚发过的微博,这时产生了不好的用户体验。通常我们会规定在写后t时间内读取master的数据,t大于mysql的主从延迟时间。

d.读后写一致性(Writes-follow-reads Consistency)

读后写一致性是指同一进程对数据项a执行的读操作之后的写操作,保证发生在于a读取值相同或比其更新的值上。

(一)满足读后写一致性(二)不满足读后写一致性

如图(一),如果变量a的初始值为0,一个进程P在L1副本上做加1操作,得到结果a=1,在a=1从L1副本传递到L2之后,进程P在L1上读到了最新的值,然后在L2上对a加1操作,得到结果2,此过程满足读后写一致性。而图(二),由于L2没有及时同步a的变化,导致进程P在L2对a加1的结果为1,不满足读后写一致性。

实际业务中,如果一个用户A在聊天室发了一条消息,用户B看到了,然后进行回复,如果副本间没有及时同步,下次请求路由到了另外一个副本,结果发现用户B发的回复还在,用户A发的内容没有了。出现了不好的用户体验。这种情况还不如用户B更晚看到用户A的消息。

业界常用的一致性模型

上面两个分类主要从学术角度进行分类,在实际情况中,大家简化了分类,主要分成了如下三个分类。

n弱一致性(Weak):写入一个数据a成功后,在数据副本上可能读出来,也可能读不出来。不能保证多长时间之后每个副本的数据一定是一致的。

n最终一致性(Eventually):写入一个数据a成功后,在其他副本有可能读不到a的最新值,但在某个时间窗口之后保证最终能读到。可以看做弱一致性的一个特例。这里面的重点是这个时间窗口。

n强一致性(Strong):数据a一旦写入成功,在任意副本任意时刻都能读到a的最新值。

最终一致性还可以继续细分,大家更喜欢把除了弱一致性和强一致性的其他一致性全部归为最终一致性。

弱一致性和最终一致性的副本同步是采用异步的方式,而强一致性一般要求同步更新副本,然后才能返回成功,否则很难满足任意副本任意时刻都能读到最新值,异步的通常意味着更好的吞吐量,但也意味着更复杂的架构,更复杂的开发、调试。同步意味着简单,但也意味着响应时间更长,吞吐量的更低。

Backups,通常不会用在生产环境;

M/S = master/slave,可以异步,也可以同步,写是瓶颈点;

MM - multi-master,可以解决写的问题,复杂度在于如何解决冲突;

2PC - 2 Phase Commit,强一致,性能低,容易死锁;

Paxos,它是完全分布的。没有单一的主协调员。

从图中可以看出,如果要满足强一致性,有两种方案:

2PC。吞吐量低,响应时间高,随着节点数增加,性能指数级下降。且容易造成死锁。

Paxos/Raft。实现成本较高。

所以,通常在满足业务场景的情况下选择最终一致性,例如聊天室只要保证最终一致性下的顺序一致性即可。

参考文献

《分布式系统原理与泛型》——作者: (美)特尼博姆

http://snarfed.org/transactions_across_datacenters_io.html

本文来自企鹅号 - 奔跑中的蜗牛媒体

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 分布式系统和一致性

    efonfighting
  • 分布式系统事务一致性

    现今互联网界,分布式系统和微服务架构盛行。业界著名的CAP理论也告诉我们,在设计和实现一个分布式系统时,需要将数据一致性、系统可用性和分区容忍性放在一起考虑。

    Bug开发工程师
  • 分布式系统事务一致性

    现今互联网界,分布式系统和微服务架构盛行。业界著名的CAP理论也告诉我们,在设计和实现一个分布式系统时,需要将数据一致性、系统可用性和分区容忍性放在一起考虑。

    Java编程指南
  • 分布式系统如何保证一致性

    随着各种高并发访问、海量数据处理等应用场景越来越多,为了应对这些使用场景,分布式系统应运而生。分布式系统得以发展,得益于诸多优点,比如:可以避免单点故障,容易横...

    大数据技术架构
  • 「数据一致性」理解分布式系统中的一致性

    多节点提供读写服务,确保高可用性和可扩展性(ZooKeeper, DNS, redis集群)

    首席架构师智库
  • 保证分布式系统数据一致性的6种方案

    在电商等业务中,系统一般由多个独立的服务组成,如何解决分布式调用时候数据的一致性? 具体业务场景如下,比如一个业务操作,如果同时调用服务 A、B、C,需要满足要...

    搜云库
  • 分布式系统一致性和共识基础(一)

    一致性是分布式系统需要解决的基础问题,一致性是对外呈现的一致的状态或结果,一致性为什么很重要,举个扫码支付的例子。

    Zeal
  • 浅谈分布式系统的一致性协议(一)

    我们在Mysql系列文章中已经介绍过,我们常用的InnoDB存储引擎是支持事务的。这里所说的事务由一系列对系统中数据进行访问与更新的操作所组成的一个程序执行逻辑...

    搬砖俱乐部
  • 分布式初探——分布式系统的一致性,究竟是什么?

    在计算机系统的领域,一致性可以说是一个高频词,可能出现的场景很多。从分布式系统到数据库的事务,都有它的身影。

    TechFlow-承志
  • 分布式系统一致性保障方案总结

    引言 在互联网系统中,理想的情况下,肯定是希望系统能够同时满足“一致性”、“可用性”和“分区容忍性”。 但是基于熟悉的CAP定律也好,还是BASE理论, 我们知...

    用户1263954
  • 分布式系统一致性问题解决实战

    商户提交表单数据至旺铺(deco项目,以下皆称为deco),deco需要接入poi系统进行装修内容的人工审核,详细流程见下图。

    后端技术探索
  • 分布式系统下的哈希一致性算法

    我们知道,在分布式系统中当数据量无法使用单机进行存储时,最简单粗暴的方法就是水平扩展:加机器,搞集群。

    Java学习录
  • 分布式系统一致性和共识基础(二)

    The Byzantine Generals Problem拜占庭将军问题是Lesilie Lamport等人 1982年发表的论文, 具体PDF链接, htt...

    Zeal
  • 分布式系统:数据一致性解决方案

    在分布式系统中,随着系统架构演进,原来的原子性操作会随着系统拆分而无法保障原子性从而产生一致性问题,但业务实际又需要保障一致性,下面我从学习和实战运用总结一下分...

    王知无-import_bigdata
  • 彻底解决分布式系统一致性问题

    首先本章内容参考《分布式服务架构》整理,思考和总结纯个人理解。 要想解决一致性问题,就要先搞明白,什么是一致性问题,一致性问题是...

    疯狂的KK
  • 简单聊聊分布式系统的一致性问题

    记得有人说过,分布式系统的所有问题归根结底都是一致性问题。前面文章提到的数据复制,分区以及事务面临的问题都是如何保证数据一致。而分布式系统不同于单机,它不...

    哒呵呵
  • 深入浅析分布式系统的一致性模型

    一致性模型指的是分布式系统对外界承诺的一个契约,外界按照契约的规定与分布式系统发生交互,就能得到契约中承诺的观测结果。

    一起学习大数据
  • 分布式系统的一致性协议—Paxos、Raft介绍

    说到系统,接触过计算机的人可能并不陌生,首先联想到的就是计算机操作系统,最熟悉的如Windows、Linux等等。可以在硬件设备上安装操作系统,有了系统就可以安...

    MySQL轻松学
  • 分布式系统的一致性协议之 2PC 和 3PC

    在分布式系统领域,有一个理论,对于分布式系统的设计影响非常大,那就是 CAP 理论,即对于一个分布式系统而言,它是无法同时满足 Consistency(强一致性...

    sunsky

扫码关注云+社区

领取腾讯云代金券