在分布式系统中有个CAP理论,对于P(分区容忍性)而言,是实际存在 从而无法避免的。
因为分布式系统是由多个节点(指代一台服务器、存储设备等)构成,由于网络异常、宕机等节点并不能保证正常工作,特别是在节点数量很大的时候,出现异常状况的节点几乎是肯定的。为了保证系统的正常运行,能够提供可靠的服务,分布式系统中对于数据的存储采用多份数据副本(注:这里的副本并非只用来备份,它可参与提供系统服务)来保证可靠性,也就是其中一个节点上读取数据失败了那么可以转向另外一个存有相同数据副本的节点读取返回给用户。这个过程对于用户来说是透明的。那么随之而来的就会带来数据的副本数据的不一致性,例如:用户提交一次修改后,那么原先保存的副本显然就与当前数据不一致了。
Quorum机制
Quorum 的定义如下:假设有 N 个副本,更新操作 wi 在 W 个副本中更新成功之后,则认为此次更新操作 wi 成功,把这次成功提交的更新操作对应的数据叫做:“成功提交的数据”。对于读操作而言,至少需要读 R 个副本,其中,W+R>N ,即 W 和 R 有重叠,一般,W+R=N+1。
-
N = 存储数据副本的数量
-
W = 更新成功所需的副本
-
R = 一次数据对象读取要访问的副本的数量
Quorum的应用
Quorum在分布式系统中的应用很多,下面举几个比较典型的例子:
1. Zookeeper
Zookeeper的选举机制是遵循了Quorum的,这也是为什么我们部署Zookeeper必须要求有奇数个Cluster可用的原因。这样一是能保证Leader选举时不会出现平票的情况,避免出现脑裂。二是Leader在向Follower同步数据的时候,必须要超过半数的Follower同步成功,才会认为数据写入成功。
其实除了Zookeeper以外,很多支持分布式部署的模块,也都遵循和使用了这个设计,比如Redis的哨兵(sentinel)机制。
2. HDFS HA
为解决NameNode的单点问题,在Hadoop 2.0对HDFS的高可用进行了改进,使得系统中可以同时启动多个NameNode,一个Active,一个Standby,并使用ZKFC(ZKFailoverController)对两者进行监控,当发现Active的NameNode服务中断,Standby的NameNode的状态会自动变为Active,接替原ActiveNameNode对外提供服务。
要想实现上面的功能,那就必然需要一个机制来确保Active和Standby这两个NameNode中的数据一致,所以在该系统中还引入了一个QJM模块,全称为Quorum Journal Manager。该模块一般由奇数个结点构成,每个QJM结点对外有一个RPC接口,以供Active NameNode向QJM写入EditLog(操作日志),此时会要求半数以上的QJM都写入成功,才算此次操作成功。Standby的NameNode也会定期从QJM上获取最新的EditLog来更新自身的数据。