在分布式系统中,通常会面临如下问题:
-
分布式协调:在分布式环境下,多个节点需要协同工作,确保多个服务之间数据的一致性以及系统的可靠性。
-
分布式锁:在分布式系统中,多个节点可能需要同时访问共享资源,为了防止竞争条件和数据不一致,需要引入分布式锁机制。
-
配置管理:在分布式系统中,多个节点需要共享某些配置或数据,并且这些配置需要动态更新。
-
服务发现:在分布式系统中,节点之间需要互相发现,以便进行通信和协作,尤其是在动态扩展或缩减节点时。
-
故障恢复:在分布式环境下,单个节点可能会发生故障,因此系统需要具有一定的容错机制,以保证整体系统的可用性。
使用Zookeeper对分布式系统进行管理,可以很大程度上解决解决上述问题,其中依赖Zookeeper集群提供的强一致性策略,可以解决分布式协调中数据之间保持一致的问题。
一致性策略分为
强一致性、线性一致性、因果一致性、最终一致性、弱一致性、读己之所写一致性、会话一致性以及单调读一致性。
其中,强一致性是保证的是所有的写操作都被严格按顺序应用到系统中,所有节点在任何时间点上都能看到相同的数据状态。这意味着,当一个客户端在提交写操作后,所有后续的读操作都能看到这个写操作的结果。
ZooKeeper 实现强一致性主要依赖于 ZAB 协议(ZooKeeper Atomic Broadcast),其类似于paxos算法,这是一种专门为 ZooKeeper 设计的分布式一致性协议。那么他是如何实现强一致性的呢?
集群数据同步流程
1. leader节点统一处理写请求
在Zookeeper集群中,只有leader节点能够处理写操作,其他的follower节点都只能处理读操作,但其并不是不能接受写请求,当接收到写操作的请求时,follower节点会讲这个请求转发给leader节点来处理。
2. 生成并广播提案
Leader节点在接受到写请求后,会生成将写请求先转化成提案,并赋予zxid,然后将这份提案广播给所有的Follower节点。
3. Follower节点确认提案
Follower在接受到Leader节点的提案后,会确认当前提案的zxid是不是正确的。如果正确,则会保存当前提案的zxid,并且执行提案的事务操作但不提交,并返回确认消息ACK,等待Leader再次发送消息时,提交事务更改。
在ZooKeeper中,每个写操作(提案)都会被分配一个递增的事务ID,称为
zxid
。这个zxid
用来标识提案的顺序,确保所有节点按照相同的顺序应用这些操作,以维持数据的一致性,而Follower就根据zxid来确认当前提案是否是期待的下一次提案,已确保事务执行的正确顺序,防止因写操作顺序不一致导致数据差异,具体规则如下:
接收提案 :当Follower节点收到一个提案时,它首先会检查这个提案的
zxid
。处理过期提案 :如果这个提案的
zxid
比Follower当前已经处理的最新zxid
要小,说明这个提案是过期的,可能由于网络延迟或其他原因延迟到达。为了防止数据回滚(即不正确地应用旧的、更早的数据),Follower会直接忽略这个提案,不会保存或执行它。处理未来提案 :如果Follower收到的提案
zxid
比它当前期望的zxid
要大,这意味着一些提案在传输过程中丢失了或尚未到达。为了保持数据一致性,Follower会先保存这个提案,但不会立即执行。它会等待缺失的提案到达,并在提案顺序完整时,按顺序执行所有提案。读请求处理:在等待缺失提案的过程中,Follower可能暂时无法提供最新的数据。为了避免返回不一致的数据,Follower会将接收到的读请求转发给Leader节点。Leader拥有最新的提交状态,因此能够返回最准确的数据。
4. Leader节点返回成功消息
当Leader节点在接受到一半以上的Follower节点的确认消息后,其就认为当前集群已经可以同步所有写操作,Leader就会通知所有从节点本次提案通过,从节点接收到这个消息后就会提交提案中的事务操作的结果,并且Leader此时会返回给客户端操作成功的响应。
整个流程比较好理解,但不好理解的是整个流程的意义是什么?
意义
1. 高可用
高可用比较好理解,任何中间件的集群模式都是具有高可用的作用,其同步所有数据到每个节点,可以防止因为Leader节点的意外宕机导致导致数据丢失,尤其是在zookeeper这样一个强一致性的要求下,节点之间数据差异的恢复速度极快,数据丢失概率极低。
zookeeper采用提案和确认提案的方式可以确保数据同步中,一半以上的节点都是可以正常接收提案并执行事务的。
当出现网络分区的问题时,一半以上的确认机制也可以使分区后的多个区域中,最多只有一个区域可以执行事务,这样可以防止两个leader同时执行不同的事务导致脑裂。
2. 强一致性
Zookeeper等待大多数节点预先执行完事务操作后返回给客户端成功响应,并且同时给Follower节点发送提案通过的消息,使其提交提案中的事务更改。通过这一过程,Zookeeper大大减少了客户端接收到成功响应到数据同步之间的时间,实现近乎强一致性,不过由于网络速度具有差异,肯能会有一定延迟。如果强行实现一致性,势必会极大的影响性能。
如果对于一致性有着极其严谨的要求,可以在获取数据之前执行sync指令,这个指令会从Leader拉取日志,同步数据,以达到数据最新的目的。