分布式系统

简介:

在全球范围构建可靠的分布式系统,需要在一致性和可用性之间进行权衡。


最终一致性  Eventually Consistent


作者: Werner Vogels

Werner Vogels is vice president and chieftechnology officer at amazon.com, where he is responsible for driving thecompany’s technology vision of continuously enhancing innovation on behalf ofamazon’s customers at a global scale.


Amazon云计算的基础是一些基础设施服务,比如Amazon的S3、SimpleDB、和EC2(弹性计算云)来提供资源,构建互联网范围上的计算平台以及大量丰富的应用。对这些基础设施的要求是非常严格;它们需要在安全性、扩展性、可用性、性能,以及能耗方面获得很高的分数,它们需要在满足这些要求的同时不间断的服务全球数百万的用户。

藏在这些服务背后,是运行在全球范围上的大规模分布式系统。全球范围带来了新的挑战,当一个系统需要处理数以万亿的请求时,平时很低概率的事件也必然会出现,必须在设计和构建系统的前期将其考虑进来。考虑到在世界范围内运行这些系统,我们无处不在地使用复制技术来获得一致的性能和高可用性。

尽管复制让我们接近了我们的目标,但它仍不能以一种透明的方式完美的实现他们;在若干环境下,服务的用户将会面临,在服务内部使用复制技术的不足。这个一点在系统提供的数据一致性类型方面就有所体现。特别是许多普遍的大规模分布式系统在数据复制时提供最终一致性模型。在Amazon设计大规模系统时,我们使用了一系列与大规模数据复制相关的指导原则和抽象概念,集中在对高可用性和数据一致性之间进行权衡。这里,我介绍一些相关背景,它们启发我们设计了在全球范围内可靠运行的分布式系统。

历史的角度

在理想的世界中,只有一个一致性模型:当一个更新发生,所有观察者都能看到更新。在1970年代后期,第一次发现这个模型难以实现。关于这个话题最好的“period piece(历史文章)”文章是“Notes on DistributedDatabases” by Bruce Lindsayet.它奠定了数据库复制的基本原则,讨论了实现一致性的许多技术。这些技术中的大部分试图透明地实现分布式,对于用户,它展现为一个系统而不是大量的协作系统。那个时期的许多系统都采用这种方法,宁可系统实现失败,也不愿破坏透明性。(批注:由此可见大师级永远是少数,其他人都是沿着大师级人物给出的方向前进)

在1990年代中期,随着更大规模的网络系统出现,之前的实践被重新审视。那时人们开始考虑,将可用性作为系统最重要的属性,但人们仍挣扎于什么需要被牺牲。Eric Brewer, UC Berkeley的系统教授,同时是Inktomi的带头人,在2000年PODC会议上一个主题演讲中将不同的权衡方面放在一起。他提出了CAP理论,对于一个数据共享系统:数据一致性、系统可用性、网络分区容忍性,在任意时刻仅能同时满足两点。更加正式的描述在2002年的论文中可以被找到,由Seth Gilbert 和 Nancy Lynch撰写。

一个系统如果不进行网络分隔,通常采用事务协议,来同时获得数据一致性和可用性,。客户端和服务器通常处于相同环境下,在某些情况下他们作为一个整体而失效,就这点而言客户端不会观察到分隔情况。在较大的分布式系统中,网络分隔是必然的;因此,一致性和可用性不可能同时被达到。这意味着有两种选择:放松一致性将使系统在分隔环境下获得高可用性;优先考虑一致性,则在某些情况下系统不可用。

对于两种选择,客户端开发人员明确知道系统提供的是那一种。如果系统强调一致性,开发人员则需要处理系统无法访问的情况,比如写请求。如果因为系统不可用而无法写入,开发人员需要处理被写入的数据。如果系统强调可用性,它将接受写入,但在某些情况下读请求不能获得最新写入的结果。开发人员需要决定客户端是否需要随时都访问最新的更新。有很多应用可以容忍轻微的脏数据,在这个模型下他们能很好的工作。

(思考:在构建大型系统时,对每一个子系统都将有很严格的响应时间、一致性等指标要求,不然大系统将无法构建。)

在这个原则下(CAP理论),事务系统的一致性属性被定义为ACID(atomicity, consistency, isolation, durability)是一种不同类型的一致性保证。在ACID中,一致性保证当一个事务完成时数据库处于一致的状态;例如,当从一个账户转钱到另一个账户,两个账户的总数是不变的。在基于ACID的系统中,通常由编写事务的开发人员负责一致性,数据库的完整性约束能辅助开发。

一致性—客户端和服务器

有两种方式看待一致性。一种是从开发者/客户端的角度:他们是如何观察数据更新的。另一种是从服务器端:更新是如何在系统中流动以及对于更新系统能提供什么样的保证。

客户端观察到的一致性指的是,何时以及如何能观察到对存储系统中数据对象所做的更新。下面的例子说明不同类型的一致性,进程A对一个数据对象进行了更新。

强一致性。当更新完成,后续所有访问都将获得更新值。

弱一致性。系统不能保证后续访问都将获得更新值。在更新返回前有许多条件需要被满足。从收到更新到所有观察者能看到更新的这段时间被称为不一致窗口

最终一致性。一种特殊的弱一致;存储系统保证如果没有新的更新提交,最终所有的访问都将获得最后的更新。如果没有故障发生,不一致窗口的大小取决于通信延迟,系统负载,以及复制策略中涉及的副本数。最常见实现最终一致性的系统是DNS。对于name更新的传播依赖,配置模式以及基于时间控制的缓存;最终,所有的节点将会看到更新。

最终一致性模型有很多变种需要重视。

因果一致性。如果进程A告诉进程B它更新了数据,接下来进程B的访问将会获得更新数据,进程B的写操作也将取代原先的写。进程C与进程A没有因果关系,则遵循最终一致性原则。

Read-your-wirtes一致性。对于进程A这是一个很重要的模型,在更新了一个数据项后,进程A后续访问到的都是更新后数据,绝不会看到旧值。这是因果模型的一个特例。

Session一致性。这是Read-your-writes模型的一个现实版本,当一个进程在一个上下文环境中访问存储系统。只要Session存在,系统将保证read-your-writes一致性。如果因为某种故障让Session中断,一个新的Session将被创建,同时保证不能重叠Session.

单调读取一致性。如果一个进程看到对象的一个特定值,那么后续所有访问将不会返回任何之前的值。

单调写一致性。这种情况下,系统保证串行化来自同一个进程的写操作。众所周知,系统如果不能保证单调写一致性,上层的程序将非常难以开发。

这些属性是可以同时具备的。例如,可以通过保证单调读和session-level一致性。从实际角度出发,这两种一致性(单调读和read-your-writes)在最终一致性系统中是最需要的。

从这些变种中你可以看到,还是有相当多的不同情境存在。它依赖于特定应用是否能处理这些后果。

最终一致性对于极端的分布式环境下并不是深奥的特性。现代的RDBMs提供的主-备可靠性,通过同步和异步的复制技术实现。在同步模式下,复制更新是事务的一部分。在异步模式中,更新以一种延迟方式到达备份节点,通常通过日志传输。在后者模型中,如果主节点在日志传送完成前失效,从远程备份节点读取到的将是旧的,不一致的数据。为了支持更好的扩展读性能,RDBMSs开始提供从备份中读取的能力,这是一种提供最终一致性保证的经典方式,其中不一致窗口依赖于日志传送的周期。

在服务器端,我们需要深入的观察更新是如何流经系统的,从而理解是什么造成了模型的不同,使用系统的开发人员能体会到这一点。让我们在开始前先创建一些定义:

N=存储副本数据的节点数。

W=需要接收更新的节点数,在完成更新前。

(注释:更新完成指将更新写入N个节点,但系统可以在写入W个节点后就返回更新完成,剩余N-W个节点在后续进行同步。)

R=读操作获取数据时需要连接的副本数。

(注释: 读取数据时从R个节点同时读取,经过合并去除掉不合理数据再返回给用户。)

如果W+R>N,写操作和读操作请求节点集会存在重叠,从而保证强一致性。在主-备的RDBMS场景中,采用同步复制,N=2,W=2,R=1。无论客户端从哪一个副本读取,它总能获得一致的结果。在异步复制模式下,允许客户端从备份节点读取,N=2,W=1,R=1。这时R+W=N,一致性不能获得保障。

W、R、N的配置是法定人数协议的基础。当因故障造成系统无法写入到W个节点时,写操作失败,系统不可用。在N=3,W=3而只有两个节点可用时,那么系统将写失败。提供高性能、高可用性的分布式存储系统,通常节点数大于2个。系统如果关注的重点是容错通常设置N=3(W=2以及R=2)。系统为了满足更高的读取负载,通常保存数据副本的节点数会超过容错需要的节点数;N可能是几十甚至几百个节点,R设置为1,这样读取到一个节点就会返回结果。系统如果关注一致性将会把更新节点数W设置为N,这可能会降低写成功的可能性。一个关心容错而不是一致性的系统通常设置W为1,获得最小的持久化开销,然后依靠周期写入技术来更新其它节点。

如何配置N,W和R取决于常见的应用是什么,以及什么路径需要优化。R=1,N=W为读应用进行优化,W=1,R=N为了更快的写进行优化。当然在后一种情况下,当故障发生时持久化不能保证,如果W<(N+1)/2,因为写操作未重叠,可能会出现冲突写。

(注释:如果W<(N+1)/2,两个客户端的写请求集合就有可能不重叠,如果两个客户端修改同一个对象,每个客户端的修改都是有效的,但系统中保存的结果却是冲突的。)

弱/最终一致性在W+R<=N时就会采用,这意味着读集合与写集合没有重叠。如果不是专门配置或基于失败案例,这里并没有特别的意义将R设置为1以外的值。W+R<=N通常发生在两种十分常见的场景:前面提到的为了获得读请求的伸缩性进行大规模复制;以及对于数据访问非常复杂的情况。在简单的Key-value模型中,通过比较版本来决定写入系统的最后更新非常容易,但对于返回对象集合的系统很难决定最新的集合应该是什么。这大多数这样的系统,写集合通常小于副本节点,然后以惰性方式将更新应用到其他副本节点。所有副本节点获得更新的周期就是前面提到的不一致窗口。如果W+R<=N,系统从节点读取数据是脆弱的,因为节点可能还没有收到更新。

是否是read-your-write, session, 以及单调一致,取决于客户端对于服务器的“粘性”,以及他们之间执行的分布式协议。如果每次访问同一个服务器,相对来讲比较容易获得read-your-writes和单调读一致性。这使得负载均衡和容错稍微难以管理,但这是一个简单的方案。使用session,具有一定粘性,让一致性非常明显,提供了一个清晰的一致性级别,客户端可进行推理。

有时客户端实现了read-your-writes和单调读一致性。通过增加写入时版本信息,客户端可以丢弃先于最近可见版本的读取值。

分区发生指,系统中一些节点无法连接其它节点,同时这两部分节点都可以被客户端访问。如果你用经典的多数法定人方法,有W副本节点的分区可以继续进行更新,而其他分布则不可用。这对于读集合一样。考虑读写集合的重叠,定义W,R时需要避免最小的不可用集合。分区并不频繁发生,但确实发生数据中心之间、以及数据中心内部。

在一些应用中,任何一个分区的不可用都是不可接受的,对于需要访问分区来获得进展的客户端来说非常重要。这种情况下,两边分配一组新的存储节点来接收数据,分区愈合时执行合并操作。例如,在Amazon的购物车中,用户使用一个write-always系统;当分区发生时,客户能继续将物品放入购物车中,即使原来的购物车在其它分区。一旦分区愈合,购物车应用将合并购物车。

Amazon’s Dynamo

考虑了所有这些属性,并在一个应用架构下可显示控制这些属性的系统是Amazon的Dynamo,一个key-value存储系统,在构成Amazon电子商务平台服务的内部使用,同时也作为Amazon的一个Web服务。Dynamo的设计目标之一就是,让在Dynamo(通常会跨多个数据中心)上创建存储实例的应用服务拥有者,能在一个合理的成本点上获得一致性、持久化、可用性以及性能的一个平衡。

总结

在大规模可靠地分布式系统中,出于两个原因数据不一致必须被接收:在高并发环境下优化读写性能;尽管节点启动并在运行,但分区问题仍是一个主要的模型,对系统不可用负有一定的责任。不一致性是否能被接收依赖于客户端的应用。在任何情况下,开发人员必须清楚存储系统提供的一致性保证,在开发应用时必须将一致性考虑进来。

这有大量方法来改善最终一致性模型,比如session级的一致性和单调读,这对于开发人员来说提供了更好的工具。很多时候,应用使用提供最终一致性的存储系统没有任何问题。在web应用中有一个非常流行的例子,我们都知道用户可接受的一致性。在这个场景下,不一致窗口一定要小于用户对返回下一个页面的期望时间。这是下一次读请求前,更新传播到整个系统的时间。

本文的目标是提高对工程系统复杂性的认识。这样的系统需要在全球范围运行,需要仔细的调优来保证他们能提供上层应用需要的持久化、可用性、以及性能。系统设计人员可用的一个工具是不一致窗口的长度,在这个过程中,系统的客户端可能被暴露给真实的大系统工程。










本文转自 h2appy  51CTO博客,原文链接:http://blog.51cto.com/h2appy/1227143,如需转载请自行联系原作者
目录
相关文章
|
1天前
|
负载均衡
分布式系统
分布式系统
10 3
|
6月前
|
消息中间件 Java 关系型数据库
分布式系统第五讲:分布式事务及实现方案
分布式系统第五讲:分布式事务及实现方案
|
9月前
|
算法 NoSQL 分布式数据库
如何在分布式系统中实现一致性?
如何在分布式系统中实现一致性?
227 0
|
11月前
|
存储 消息中间件 监控
在学习分布式系统时遇到的五个常见误解
在学习分布式系统时遇到的五个常见误解
11018 1
|
存储 分布式计算 负载均衡
分布式系统是什么
分布式系统是什么
222 0
|
存储 缓存 监控
常见分布式系统-终版 | 学习笔记
快速学习常见分布式系统-终版
307 0
常见分布式系统-终版 | 学习笔记
|
存储 SQL Java
理解「分布式系统」曾经发生的事情
理解「分布式系统」曾经发生的事情
理解「分布式系统」曾经发生的事情
|
存储 消息中间件 缓存
什么是分布式系统,如何学习分布式系统?
什么是分布式系统,如何学习分布式系统?
457 0
什么是分布式系统,如何学习分布式系统?
|
消息中间件 运维 负载均衡
到底什么是分布式系统?
分布式系统背景 说分布式系统必须要说集中式系统,集中式系统中整个项目就是一个独立的应用,整个应用也就是整个项目,所有的东西都在一个应用里面。
|
存储 消息中间件 缓存
什么是分布式系统,这么讲不信你不会
本文的目标是给打算全面学习分布式系统的自己、以及感兴趣的读者指明一条可行的路径,使得之后的学习不再盲目。不过,我并没有越过这座山,我只是站在山前,从前人留下的痕迹揣测山的全貌与沟壑,臆想的成分居多,还望各位大师指点迷津。
什么是分布式系统,这么讲不信你不会

相关实验场景

更多