Zookeeper(二)——ZK实现分布式锁(读写锁、羊群效应、curator实现)、zk的watch机制(客户端和 curator )、ZK 集群搭建、ZAB协议(选举和崩溃恢复、主从数据同步)
Zookeeper(二)——ZK实现分布式锁(读写锁、羊群效应、curator实现)、zk的watch机制(客户端和 curator )、ZK 集群搭建、ZAB协议(选举和崩溃恢复、主从数据同步)
Zookeeper(二)——ZK实现分布式锁(读写锁、羊群效应、curator实现)、zk的watch机制(客户端和 curator )、ZK 集群搭建、ZAB协议(选举和崩溃恢复、主从数据同步)
一、ZK实现分布式锁
1、zk中锁的种类
- 读锁(读锁共享-共享锁):大家都可以读。上锁前提:之前的锁没有写锁
- 写锁(写锁排他-排他锁):只有得到写锁的才能写。上锁前提:之前没有任何锁
2、zk如何上读锁
- 创建一个临时序号节点,节点的数据是read,表示是读锁
- 获取当前zk中序号比自己小的所有节点
- 判断前面的节点中是否有写锁
- 获取读锁时会创建一个临时节点并查看前面的节点是否有写锁
- 如果满足上述条件,则上锁成功。
3、zk如何上写锁
- 创建一个临时序号节点,节点的数据是write,表示写锁
- 获取zk中所有的子节点
- 判断自己是否是最小的节点:
- 如果是,则上写锁成功
- 如果不是,说明前面还有锁,则上锁失败,监听最小节点,如果最小节点有变化,则再执行第二步。
之所以要判断自己是否是最小节点,因为如果是最小节点,则立马可以上锁。
4、羊群效应
如果用上述的上锁方式,只要有节点发生变化,就会触发其他节点的监听事件,这样对zk的压力非常大。
如果有100个并发,都要上写锁,但是目前已经有一个锁存在,则这100个并发都会去监听第一个锁,如果第一个锁发生变化,则这100个节点只有一个能成功,接着剩下99个又去监听这一个节点,这样会对 zk 的压力非常大。
而羊群效应,可以调整成链式监听。解决这个问题:
每个节点都只要监听上一个节点即可。
如果三节点断开了,则四节点会去监听2节点。
5、curator 实现读写锁
a、获取读锁
b、获取写锁
二、zk 的 watch 机制
1、Watch 机制介绍
我们可以把Watch理解成是注册在特定Znode上的触发器。当这个Znode发生改变,也就是调用了create,delete,setData方法的时候,将会触发Znode上注册的对应事件,请求Watch的客户端会收到异步通知。
具体交互过程如下:
- 客户端调用getData方法,watch参数是true。服务端接到请求,返回节点数据,并且在对应的哈希表里插入被Watch的Znode路径,以及Watcher列表。
当被Watch的Znode已删除,服务端会查找哈希表,找到该Znode对应的所有Watcher,异步通知客户端,并且删除哈希表中对应的key-value。
客户端使用了 NIO 通信模式监听服务端的调用
a、get -w /xxx —— 一次性监听某个节点
监听 test9 节点,当9节点发生变化,比如:
那么监听的变化信息:
可以看到,这里只会告诉我们发生了变化,但是发生了什么变化还是需要自己去操作相关命令去查看。
如果是删除节点,那么告诉我们的信息会发生变化:
如果是创建子节点,监听并不会被触发。
2、zkCli客户端使用Watch
create /test date
get -w /test 一次性监听节点。
ls -w /test 监听目录(只监听目录)。创建和删除子节点会收到通知,但是子节点中新增节点不会被监听到。
ls -R -w /test 监听子节点中节点的变化,但内容的变化不会收到通知。
3、Curator客户端使用Watch
当服务端节点数据发生变化时:
三、ZK 集群
1、ZK 集群角色
zookeeper集群中的节点有三种角色
- Leader:处理集群的所有事务请求,集群中只有一个Leader
- Follwoer:只能处理读请求,参与Leader选举
- Observer:只能处理读请求,提升集群读的性能,但不能参与Leader选举
2、集群搭建
先把开启的单节点服务停止。
先进到该目录下:
/root/apache-zookeeper-3.7.1-bin/zkdata
然后创建四个文件夹:
然后每个 zk 的文件夹都需要创建一个文件,叫 myid,然后给一个值,这个值是描述该节点(是服务器节点)的唯一标识,这个值不能重复。
然后重新进入 conf 目录,准备四个 zoo.cfg 配置文件去启动四台 zk:
然后修改 zoo1.cfg 配置文件:
上面的 abserver 打错了,是 observer。
保存后再复制三份,zoo2 zoo3 zoo4 。
然后修改这些复制出来的配置文件,只需要修改日志路径,还有对客户端的端口号即可:
3、4同理。
接着启动这四个文件:
可以通过下面命令查看是什么状态的机子:
四、ZAB协议
1、什么是ZAB协议
zookeeper作为非常重要的分布式协调组件,需要进行集群部署,集群中会以一主多从的形式进行部署。zookeeper为了保证数据的一致性,使用了ZAB(Zookeeper Atomic Broadcast)协议,这个协议解决了Zookeeper的崩溃恢复和主从数据同步的问题。
2、ZAB协议定义的四种节点状态
- Looking:选举状态
- Following:Following节点(从节点)所处的状态
- Leading:Leader节点(主节点)所处状态
- Observing:观察者节点所处的状态
3、集群上线Leader选举过程
4、崩溃恢复时的Leader选举
Leader建立完后,Leader周期性地不断向Follower发送心跳(ping命令,没有内容的socket)。当Leader崩溃后,Follower发现socket通道已关闭,于是Follower开始进入到Looking状态,重新回到上一节中的Leader选举过程,此时集群不能对外提供服务。
5、主从服务器之间的数据同步
看第六步,可以看到是半数以上的 ack,这个半数是对候选还是整个集群?
这个半数是针对整个集群,可以很明显看到候选中数量是偶数,如果是半数以上,只有奇数才好判断半数以上。
6、Zookeeper中的NIO与BIO的应用
- NIO
- 用于被客户端连接的2181端口,使用的是NIO模式与客户端建立连接
- 客户端开启Watch时,也使用NIO,等待Zookeeper服务器的回调
- BIO
- 集群在选举时,多个节点之间的投票通信端口,使用BIO进行通信
7、Zookeeper追求的一致性
Zookeeper在数据同步时,追求的并不是强一致性,而是顺序一致性(事务id的单调递增)
更多推荐
所有评论(0)