副本协议
副本控制协议指按特定的协议流程控制副本数据的读写行为,使得副本满足一定的可用性和一致性要求的分布式协议。副本控制协议要具有一定的对抗异常能力,从而使得系统具有一定的可靠性,同时还得提供一定的一致性级别。
中心化副本控制协议
中心化副本控制协议指的是由中心节点协调所有节点的更新与维护各个副本之间的一致性。优点把关于分布式上的并发问题转换为了一个单机的并发问题,缺点当中心节点异常的时候或者中心节点通信中断时,系统将停止某些服务(失去 更新数据的服务),所以中心化副本控制协议缺点在于缺少当中心节点挂掉,整个系统会停止一段服务的时间。
primary-secondary(master-slave)
在这种中心化副本控制协议中,primary称为主节点,secondary称为备节点。中心节点负责维护数据的更新、并发控制、一致性。
primary-secondary 数据更新基本流程
数据更新基本流程如上。当备节点同步操作完成向外部节点返回成功否则失败。在实际中,如果只由Primary副本去同步数据,那么每个Secondary副本同步速度只有Primary副本节点上带宽的 1/N (N指Secondary节点个数)。为了解决这个问题,某些系统使用接力的方式同步数据,primary成功同步第一个secondary副本后,由该secondary副本同步后续的secondary副本,最终达到每个secondary副本与Primary副本一致,它实际上就是满足了最终一致性,对于同步操作有很多处理在下文继续讨论。
primary-secondary数据读取方式
Primary-secondary 强一致性的思路
- 将数据分段,这样primary副本的数据分布到所有的机器上,每次读取数据的时候通过元信息服务器读primary副本的分布,然后每次更新只更新primary副本随后再同步到secondary。读取的时候也只读取primary副本,这样就可以实现强一致性。
- 由primary控制secondary节点的可用性。当primary同步某个secondary副本失败的话会将其标识为不可用,从而用户不再读取该不可用的副本,直到后续同步成功才标记为其可用。这样也可实现一致性要求,但是它降低了可用性(也就是在异常情况下分布式系统仍然可用正常工作的特性)。
- Quorum机制
primary 副本切换
切换副本的难点在于俩个方面,首先如何确定primary节点状态异常。其次,进行切换primary后能不能保持一致性。
第一个问题可以通过Lease(租约机制)实现,第二个问题可以通过将标记为可用的secondary节点选为primary节点解决,也可以通过Quorum机制解决下文描述。
primary - secondary优点
比较简单就可以实现强一致性
primary - secondary 缺点
当primary挂掉的时候,分布式系统就会停止一段时间服务,可用性比较差
Quorum
Quorum机制下,当某次write操作只要在N个副本中使W个副本更新成功,wi就称为"成功提交的更新操作",vi相应的数据称为"成功提交的数据"。令 R > N - W ,从公式可以看出 只要 Read的次数大于 N-W的个数,总能读取到已更新的数据,也就是说由于W+R > N ,那么R读到的副本集合肯定与 W写成功的副本集合有交集如上图所示。
Quorum机制无法保证强一致性,虽然我们读R次肯定能读到最新的数据,但是我们无法确定这个最新的数据是不是已经成功提交的数据。仅仅通过quorum机制无法确定最新已成功提交的版本号,除非将最新的已成功提交的版本号作为元数据由特定的元数据服务器管理,否则很难确定当前读取到的最新数据是最新成功提交的版本号。强一致性系统要求读取的数据必须为最新成功提交的数据,所以怎么实现看下文
quorum强一致性读取最新成功提交的数据
如上,在N=5 , W=3 , R=3的系统中。当我们Read三次的时候,可能出现的情况如上图所示,图A中V2是最新已经成功提交的版本数据,图B中V1是最新已经成功提交的版本数据,所以我们不能仅凭读3次就判断v2是否为最新的版本数据。
因为上面这个原因,所以我们无法仅凭读R次就判断读到的某个版本数据就是最新的数据。所以还需对Quorum进行读取条件加强实现强一致性。
- 每次提交的操作必须严格按照提交顺序执行,只有前一个提交成功后才可以提交后一个更新操作,从而成功提交的数据版本号必须是连续增加的。
- 读取R个副本,对于R个副本中版本号最高的数据。如果这些版本号的副本满足W个则最高版本号为最新的成功提交的数据。否则一直读取直到读取满足W个版本的最高数据或者读完了N个副本其中最高版本号并不满足w个最高版本号那么次高版本号为最新提交的版本数据。
从上面的分析得出,如果要确定最新的成功提交的版本,最多读取N个版本,当出现任一副本异常时,读取最新的已成功提交的版本这一功能就不可使用。所以仅通过Quorum实现强一致性的读其可用性并不高。如果想解决这个问题,可以通过将quorum 与 primary-secondary 相结合使用。
Quorum 机制选择primary
为了解决上面读不可靠的问题,当需要读取数据的时候可以直接读取 primary副本的数据,如果需要更新(write)副本的时候,可以使用Quorum机制进行更新,当成功更新W个副本后就可以向用户返回成功。
在之前 primary-secondary协议中,当 primary 异常时,