乐观复制算法-附件C-一致性模型
附件C-一致性模型
对一致性模型的描述主要从三个出发点进行考虑:
(1) 响应前还是响应后,即在完成对所有副本数据集的同步前返回用户,还是完成同步后再给用户反馈。
(2) 进行同步对象的多少,是对每次更新进行同步还是在多次更新后再同步。
(3) 对更新顺序的维护,维护更新操作间不同的顺序会提供不同的一致性,当完全不考虑更新顺序,甚至更新的类型时,只提供最终数据的相互一致,则是最终一致性。
1.相互一致性
文献[70]对一致性的定义为,设定在数据上的约束。这种约束在不同应用中是不同的。违反这样的约束就称违反了数据的一致性。对于分布式中,复制技术最重要的约束就是副本节点数据的相互一致。请求对一个副本上的数据进行了修改,如果系统没有及时的将更新传播并应用到其它节点,路由到其它节点的请求就会获取到不一致的数据内容。维护节点间的相互一致性就称为了复制系统的关键。同时一致性模型也是数据同步的重要模型。
Yu和Vahdat 2002[13]为定义副本间的不一致性判断设计了三个相互独立的坐标轴:副本之间的数值偏差、副本之间新旧程度的偏差以及更新操作顺序的偏差。数据具有数值语义的应用程序可以按数值偏差来度量不一致性。例如,股票市场价格记录的复制。在这种应用中,应用程序可能会指定两个副本的偏差不能超过0.02美元,这就是绝对数值偏差。也可以指定相对数值偏差,表示两个副本之间的差别不能超过多少(0.5%)新旧偏差与副本最近一次更新有关。多某些应用程序来说,只要副本提供的旧数据不是太旧,它是可以容忍的。例如,天气预报通常要滞后一段时间(如几个小时)。在这种情况下,主服务器会定期地接收更新消息,但在一段时间内只给副本传送一次更新信息。在有些应用程序中,只要可以界定副本之间的差异,就允许不同的副本采用不同的更新顺序。
下面我们来谈一谈不同的一致性约束。不同的一致性约束是系统对外提供服务的不同特性,开发人员在使用一个存储系统前,最先应当了解该系统提供的一致性约束。
我们这里对于一致性约束的描述是以客户端-服务器为模型[52,73]。站在客户端的角度来分析客户端自己所做的更新在不同一致性约束下的不同表现结果。为了后续描述的简单,我们这里做一些约定。C表示客户端,C1,C2,C3个客户端。S表示服务器,S1和S2两个服务器。数据对象的编址为1,2,3,4,即有四个数据对象。对数据的读操作为read(i)括号内i为数据的编址。对数据的写操作为write(i,n),i为数据的编址,n为写入的数值。为了描述单调写一致性,支持write(i,++)操作,即对编址为i的数据进行自动加1操作。所有编址内数据的初始值为0。
2.强一致性
强一致性为:任意一个客户端做的更新,其它客户端在后续的访问中都能获得
我们从最简单的一致性模型开始,然后一步步增加问题的复杂性。最简单的一致性模型应该就是只有单一服务器,多客户端模型,如上图所示。垂直线表示真实时间。含有箭头的线段表示从一台电脑发送给另一台电脑的消息,线段的倾斜角度表示网络延迟,倾斜角度大,说明该消息从发送节点到达接收节点经过的时间长,故网络延迟大。上图我们忽略掉服务器S1执行操作的时间。C2的read(1)请求在C1的write(1,5)之后进行,所以将获得最新的更新内容(1,5)。同理C1的read(2)在C2的write(2,7)之后进行,将获得最新的更新内容(2,7)。
增加一台服务器,同时每个数据对象存在两个副本,分别放置在两台服务器上。由于更新需要应用在多个副本上,所以更新的执行时间就不能被忽略。从图中我们可以看到,C2多次请求数据对象1的内容。当read(1)请求在副本节点执行同步前进行,会返回(1,0)。当服务器正在执行同步时收到请求,则将不返回内容给C2,或者可以返回提示信息表示数据正在同步。当服务器完成同步后,C2的read(1)请求会得到最新的更新值(1,5)。
在多副本的系统中,系统为了保证对外提供数据的强一致性,必然会在系统的可用性上做出一定的牺牲。上图中,对于数据对象1系统在各个服务进行同步的过程中,数据对象1对外不提供服务。
3. 弱一致性
为了提高系统的可用性,在许多应用中会放松对一致性的需求。下面先来看一个例子,从而说明什么是弱一致性。然后将说明不同约束下的弱一致性。
上图中,完成多副本间的同步也需要一定的时间,但在这个时间内,系统对外一直提供服务。不过C2并不能在C1提交完更新后就获得最新的更新内容,C2会获得数据对象1的历史数据。我们称不同副本完成同步需要的时间为系统的不一致窗口。如上图,两条虚线间表示不一致窗口
弱一致性指,系统无法提供在更新完成后,任意节点都会立即获得最新的更新内容。
3.1 Read-your-write
C1在提交完write(1,5)更新请求后,紧接着提交了read(1)请求。Read-your-write一致性的约束,是保证C1将会看到自己所做的更新,即C1将会读取到(1,5)。
然后因为存在多个副本节点,C1首先提交的write(1,5)更新请求由S1执行,但是C1随后提交的read(1)请求不一定会在S1上执行。如上图,两条虚线表示不一致窗口。代箭头的虚线表示read(1)由S2执行,此时S2未完成对数据对象1的同步,那么C1将会访问到数据对象1的旧值(1,0),这就违反了Read-your-write约束。
3.2 Session consistency
Session一致性是read-your-write的一个特例。C1首先提交了write(1,5),随后提交了read(1),如果这两个请求在同一个session的作用范围内,那么C1将看到自己之前提交的更新。如上图虚线方框内的连续两个请求。如果C1的写、读两个请求并不在同一个session范围内,那么系统将不能保证后面的读请求一定会获取前面写请求的更新值。这里有多种原因为造成这样的结果。比如,两个副本节点完成同步的时间大于Session的有效期,并且C1的read(1)被负载到了未完成同步的节点。如上图,代箭头的虚线就是落在session一致性约束外的请求,获取的返回值可能是(1,0)或者(1,5)。
3.3 单调读一致性Monotonic read consistency
单调一致性指,当一个客户端在read请求时获得了某一个特定的值,该客户端随后的read请求不允许获得该数据对象之前的旧值。上图,客户端C1先后执行write(1,5)和read(1),得到(1,5)。然后C1再多次发送read(1)请求,如果后续的read(1)请求返回的结果都是(1,5)那么就称系统遵循了Monotonic read consistency。但是如上图,代箭头虚线所示,C1后续的read(1)请求的返回结果为(1,0),这就违反了Monotonic read consistency。
3.4 单调写一致性Monotonic write consistency
单调写一致性,指对于同一个客户端,它连续的写操作是基于前面写操作的结果进行。上图中,C1发起连续的两个写操作,分别是write(1,5),write(1,++),即先将数据对象1设置为5,然后让数据对象1完成自动加1操作。正确的执行结果应该是(1,6)。
上图中在右侧(1,5)(1,0)表示,当某一副本节点执行完C1请求时,在两个副本节点上数据对象1的值。例如,当C1提交write(1,5),S1完成操作,S2未完成同步,则此时的数据对象1在S1上为(1,5),在S2上为(1,0)。
如果C1第二个写请求write(1,++),仍由S1执行,则C1将会看到的正确的执行结果(1,6)。但是如果请求由S2执行,C1将会看到(1,1)这样的结果,这样就违反了单调写一致性。
当然,在S1和S2完成同步后,write(1,++)由S2执行,C1仍可以看到正确的执行结果(1,6)。
3.5 因果一致性Causal consistency
前面描述的弱一致性,一直是对从一个客户端的角度分析。如果两个客户端的操作存在一定的先后顺序,该如何保证一致性。因果一致性就是对来自不同客户端,存在先后的请求提供一致性保证。
因果一致性,指如果不同客户端的请求存在先后顺序,那么多副本系统对请求的返回结果也要符合该请求间的先后顺序。
如上图,C1发送请求write(1,5),然后C1通知C2它完成更新(点线表示该通知),这时C2发送请求read(1)。如果系统对C2的read(1)返回(1,5),则该系统遵从了因果一致性,如果系统返回(1,0)则该系统并为提供因果一致性。对于无请求先后顺序关系的客户端,如C3节点,同样请求read(1),系统将不提供任何一致性保证,C3获得的返回值可能是(1,0),也可能是(1,5)。
4. 最终一致性
最终一致性是弱一致性的特例[73]。弱一致性对更新操作在不同副本节点间的传播顺序,以及执行顺序进行了约束,从而实现不同的弱一致性。最终一致性对于不同副本节点间传播的更新,执行顺序没有任何约束,甚至在节点间传播的更新并不总是用户在客户端直接执行的更新操作。最终一致性,只要求如果对于数据对象不再有任何更新后,那么最终所有的访问都将获得最后更新的值。