项目中一直依赖zooKeeper(线上环境是5个节点),这里对zooKeep最基础的知识做一个简单的介绍。
在工作中学习还是以用为主,要多问自己这个工具有什么用途?能在项目中有什么应用?
预备知识:
ZooKeeper是一个分布式的应用程序协调服务,是Google的Chubby一个开源的实现。分布式系统的一大难点在于网络是不可靠的。分布式中的节点需要互相通信,如果通信失败,可能是节点问题,也有可能是网络问题。
如果是同一台机器内多线程的协调,需要学习并发知识;而多台机器之间的协调,则需要学习分布式知识。
一、服务注册
我们的工程中dubbo强依赖zookeeper,此时的zookeeper是作为服务注册中心。根据CAP定理,一个分布式系统不可能同时满足C(一致性)、A(可用性)和P(分区容错性)。zookeeper满足的CP。如果zookeeper中的leader节点宕机,会选举新的leader,此时zookeeper会处于不可用状态,如果选举时间太长,会带来非常糟糕的后果。针对以上问题,Spring Cloud的Eureka的设计就保证了AP,其原理是每个节点是平等的(peer to peer),保证最终一致性。
二、Master选举
三个Batch Job 部署在三台机器上,但是这三个Batch Job同一个时刻只能有一个运行,如果其中某个不幸down掉,剩下的两个就需要做个选举,选出来的那个Batch Job 需要“继承遗志”,继续工作。
一个方案是利用数据库表主键不能冲突的特性,让这三个Batch Job 都向同一个表中插入同样的数据,谁先成功谁就是Master 。这个方案的漏洞是如果抢到Master的那个Batch Job挂掉了,别人永远就抢不到了! 因为记录已经存在了, 别的Batch Job 没法插入数据了!补救方案是加入定期更新的机制,master会定期更新状态,否则会认为master处于下限状态。
如果使用redis原理与上述方案类似。
如果使用zookeeper,三个Batch Job启动以后,都去注册中心争抢着去创建一个树的节点(例如/master ),谁创建成功谁就是Master (当然zookeeper必须保证只能创建成功一次,其他请求就失败了),其他两个Batch Job就对这个节点虎视眈眈地监控,如果这个节点被删除,就开始新一轮争抢,去创建那个/master节点。
使用zookeeper有一个复杂的情况, 如果机器1并没有死掉,只是和注册中心长时间连接不上,注册中心会发现Session超时,会把机器1创建的/master删除。 让机器2和机器3去抢,如果机器3成为了master, 开始运行Batch Job, 但是机器1并不知道自己被解除了Master的职务, 还在努力的运行Batch Job,这就冲突了!所以机器1感知到和注册中心断开之后,自己要停止任务。
三、分布式锁
锁是同步临界资源(共享资源)的工具,如果是在同一机器内,那么使用并发机制。如果是多态机器竞争资源,那么需要分布式锁。
这些系统在注册中心的/distribute_lock下都创建子节点, 每个节点都有编号。各个系统去检查自己的编号,谁的编号小就认为谁持有了锁, 例如系统1。
系统1持有了锁,就可以对共享资源进行操作了, 操作完成以后process_01这个节点删除, 再创建一个新的节点(编号变成process_04了)。
此时系统2持有锁。如此循环反复,分布式锁就实现了。
四、一点原理
关于zookeeper还有其他功能,这里就此打住,最后说一点zookeeper的内部原理。
1)Session: 表示某个客户系统(例如Batch Job)和ZooKeeper之间的连接会话, Batch Job连上ZooKeeper以后会周期性地发送心跳信息, 如果Zookeepr在特定时间内收不到心跳,就会认为这个Batch Job已经死掉了, Session 就会结束。(依赖心跳维持Session)
2)zookeeper的最基础的数据结构是Znode,在此基础之上定义了原语(关于数据结构的操作)。按类型可以分为永久的znode(除非主动删除,否则一直存在),临时的znode(Session结束就会删除)和 顺序znode(分布式锁中的process_01,process_02.....)
3.) Watch : 某个客户系统(例如Batch Job)可以监控znode, znode节点的变化(删除,修改数据等)都可以通知Batch Job, 这样Batch Job可以采取相应的动作,例如争抢着去创建节点。
参考资料: