WARO(Write All Read one)是一种简单的副本控制协议,当Client请求向某副本写数据时(更新数据),只有当所有的副本都更新成功之后,这次写操作才算成功,否则视为失败。
从这里可以看出两点:
①写操作很脆弱,因为只要有一个副本更新失败,此次写操作就视为失败了。
②读操作很简单,因为,所有的副本更新成功,才视为更新成功,从而保证所有的副本一致。这样,只需要读任何一个副本上的数据即可。假设有N个副本,N-1个都宕机了,剩下的那个副本仍能提供读服务;但是只要有一个副本宕机了,写服务就不会成功。
Quorum机制是“抽屉原理”的一个应用。定义如下:假设有N个副本,更新操作wi 在W个副本中更新成功之后,才认为此次更新操作wi 成功。称成功提交的更新操作对应的数据为:“成功提交的数据”。对于读操作而言,至少需要读R个副本才能读到此次更新的数据。其中,W+R>N ,即W和R有重叠。一般,W+R=N+1
假设系统中有5个副本,W=3,R=3。初始时数据为(V1,V1,V1,V1,V1)–成功提交的版本号为1
当某次更新操作在3个副本上成功后,就认为此次更新操作成功。数据变成:(V2,V2,V2,V1,V1)–成功提交后,版本号变成 2
因此,最多只需要读3个副本,一定能够读到V2(此次更新成功的数据)。而在后台,可对剩余的V1 同步到V2,而不需要让Client知道。
仅仅通过Quorum机制无法确定最新已经成功提交的版本号。
比如,上面的V2 成功提交后(已经写入W=3份),尽管读取3个副本时一定能读到V2,如果刚好读到的是(V2,V2,V2),则此次读取的数据是最新成功提交的数据,因为W=3,而此时刚好读到了3份V2。如果读到的是(V2,V1,V1),则无法确定是一个成功提交的版本,还需要继续再读,直到读到V2的达到3份为止,这时才能确定V2 就是已经成功提交的最新的数据。
(如果读到(v1,v1,v2),这种情况是不能马上给客户端返回的,因为不管返回v1还是v2,都可能不对。在Quorum下,此时还无法确认最新成功的版本是v1还是v2,因此还需要继续读,只有某个版本读到>=W才能确认。)
1)如何读取最新的数据?—在已经知道最近成功提交的数据版本号的前提下,最多读R个副本就可以读到最新的数据了。
2)如何确定 最高版本号 的数据是一个成功提交的数据?—继续读其他的副本,直到读到的 最高版本号副本 出现了W次。
中心节点(服务器)读取R个副本,选择R个副本中版本号最高的副本作为新的primary。
新选出的primary不能立即提供服务,还需要与至少与W个副本完成同步后,才能提供服务—为了保证Quorum机制的规则:W+R>N
至于如何处理同步过程中冲突的数据,则需要视情况而定。
比如,(V2,V2,V1,V1,V1),R=3,如果读取的3个副本是:(V1,V1,V1)则高版本的 V2需要丢弃。(可以理解为写入失败,没有超半数)
如果读取的3个副本是(V2,V1,V1),则低版本的V1需要同步到V2