分布式锁为我们保证了在分布式环境中数据的一致性。
ZooKeeper的分布式锁有两种:1.独占锁 2.读写锁。
1.独占锁的原理
独占锁也叫排他锁,顾名思义的就是锁只能被一个客户端拥有。
当客户端a1访问z1资源时,会在z1节点下创建锁lock节点,这个时候有其他客户端来访问z1资源时发现z1已经加锁,则无法访问到z1资源,于是其他客户端就会对lock节点设置watcher。当持有锁的客户端删除节点lock(即断开链接)或者奔溃,则有ZooKeeper删除lock节点,由于lock节点的变化,其他客户端收到通知后再次去争取创建lock节点获取锁(访问z1资源的权限),以此重复步骤如下:
1.多个客户端竞争创建lock临时节点获取锁
2.某个客户端创建lock临时节点成功,其他客户端对lock设置watcher。
3.持有锁客户端删除lock节点或者奔溃
4.其他客户端收到通知
5.重复1到4步骤,直至无客户端等待访问该资源
2.读写锁的原理
读写锁也叫顺序锁,顾名思义就是“根据顺序获取锁”。
读写所分读锁和写锁,当一个资源被加读锁时,其他客户端也可以对该资源加读锁,可以资源共享,当资源被加写锁时,其他客户端将不能访问该资源,读锁具有共享性而写锁具有排他性。
读写锁和独占锁获取锁的方式不同,读写锁的客户端不用在去竞争创建lock临时节点,所有的客户端都会去创建临时顺序节点,节点创建成功后获取所有的临时顺序节点,判断是否获取锁,获取读锁的条件:
1.临时顺序节点的序号排在其他节点之前
2.没有写锁
获取写锁只需要满足上面的条件1即可。
读写锁的获取步骤如下:
1.所有客户端创建临时顺序节点
2.获取节点下所有的锁,并对这个节点设置watcher
3.客户端判断自己是否成功获取锁,如果没有则继续等待
4.持有锁的客户端删除锁,其他客户端收到通知
5.重复以上2到4步骤,直到没有客户端等待获取锁
以上方式有个缺点就是当锁被删除时,服务器会向客户端发送大量的事件通知(“惊群效应”),所以当集群多的时候可以进一步优化,其他客户端的只需要监听我们关心的临时顺序节点,即监听比自己顺序号小一的顺序号的锁即可。