1、分布式锁是什么
分布式锁是控制分布式系统之间同步访问共享资源的一种方式。
项目在单台服务器上部署时如果有资源竞争问题一般使用synchronized或ReentrantLock来解决。当项目部署在不同的机器上在考虑资源竞争时需要用分布式锁。
2、Zookeeper实现分布式锁
使用ZooKeeper实现分布式锁——排他锁和共享锁的实现。
排他锁只对一个事务可见,共享锁对所有事务可见。
2.1排他锁
排他锁简称X锁,又称为写锁或独占锁。如果事务T1对数据对象O1加上排他锁,那整个加锁期间只允许事务T1对O1进行操作,其他任何事务都不能对O1进行任何操作,至到T1释放了排他锁。
Zookeeper中的排他锁
定义锁:Zookeeper中通过ZooKeeper上的数据节点来表示一个锁,如下图所示
排他锁流程
获取锁:
获取排他锁时,ZooKeeper所有的客户端会尝试通过调用create()接口,在、exclusive_lock节点下创建临时子节点、exclusive_lock/lock。ZooKeeper会保证最后只有一个客户端能创建成功,那么此时创建成功的客户端获取到锁。这时其他没有获取到锁的客户端就在/exclusive_lock节点上注册一个子节点变更的Watcher监听,实时知道lock节点的变更情况。
释放锁:
锁是一个临时节点,当获取锁的客户端宕机(移除临时节点)或者执行完业务流程(删除临时节点)时会释放锁。只要该临时节点移除后ZooKeeper就通知所有在该节点上注册了变更监听的客户端,这些客户端会重新获取锁。
2.2共享锁
共享锁简称S锁,又称为读锁。如果事务T1对数据对象O1加上了共享锁,那么当前事务只能对O1进行读取操作,其他事务也只能对这个数据对象加共享锁——直到该数据对象上所有的共享锁都释放。
Zookeeper中的共享锁
定义锁:同样Zookeeper中通过ZooKeeper上的数据节点来表示一个共享锁(临时顺序节点),如下图所示
共享锁流程
获取锁
所有的客户端都会在/shared_lock节点下创建一个临时顺序节点,读请求节点—— /shared_lock/192.168.0.1-R-0000000001,写请求节点——/shared_lock/192.168.0.1-W-0000000001。
判断读写顺序
共享锁中不同的事务都可以对同一个数据对象进行读操作,但是更新操作必须是在当前没有任何事务进行读写的操作时进行。
通过ZooKeeper的节点来确定分布式读写顺序如下:
1、创建完节点,获取/shared_lock节点下所有子节点,并对该节点注册子节点变更的Watcher监听。
2、确定自己的节点序号在所有请求子节点中的顺序。
3、读请求:
没有比自己序号小的子节点,或是所有比自己序号小的子节点都是读请求,那么这时就可以进行读取操作。一旦比自己小的节点有写操作就需要等待。
写请求:
如果自己不是序号最小的子节点,那么就需要进入等待。
4、监听变更通知后继续步骤1。
释放锁
同排他锁