Zookeeper分布式锁实现Curator十一问(五)
八、如何实现公平锁
其实使用临时顺序节点实现的分布式锁就是公平锁。所谓的公平锁就是加锁的顺序跟成功加锁的顺序是一样的。
因为节点的顺序就是被唤醒的顺序,所以也就是加锁的顺序,所以天生就是公平锁。
九、如何实现读写锁
读写锁使用如下。
创建节点的时候,节点的内容中会有一个标记来代表当前节点加的是什么类型的锁。
当需要加写锁时,需要判断自己创建的节点是否排在第一位,如果是就能加锁成功,所以一旦前面有节点,不论前面加是读锁还是写锁,那么都是加锁失败,实现了读写互斥和写写互斥。当然写锁和读锁都是可以重入加锁的。
当需要加读锁的时候,会去判断自己创建节点的前面有没有写锁,如果没写锁,那么说明前面加的都是读锁,那么读锁就能加锁成功,读读不互斥,如果前面有写锁,那么就加锁失败(自己加的写锁除外),读写互斥。
十、如何实现批量加锁
批量加锁的意思就是同时加几个锁,只有这些锁都算加成功了,才是真正的加锁成功。
Redisson也实现了批量加锁的功能,Redisson的实现通过RedissonMultiLock类实现的,RedissonMultiLock会去遍历需要加的锁,然后每个都加成功之后才算加锁成功。Curator是封装了InterProcessMultiLock类来实现的批量加锁的,那么InterProcessMultiLock如何实现的呢?
使用代码如下。
InterProcessMultiLock的acquire的方法实现。
从这里可以看出,InterProcessMultiLock也是遍历传入的锁,然后每个锁都加锁成功了,InterProcessMultiLock才算加锁成功。
所以从这里可以看出,跟Redisson实现的批量加锁的实现思想上基本是一样的,都是遍历加锁。
十一、ZK分布式锁和Redis分布式锁到底该选谁
这是一个比较常见的面试题。
redis分布式锁:
- 优点:性能高,能保证AP,保证其高可用,
- 缺点:正如Redisson的那篇文章所言,主要是如果出现主节点宕机,从节点还未来得及同步主节点的加锁信息,可能会导致重复加锁。虽然Redis官网提供了RedLock算法来解决这个问题,Redisson也实现了,但是RedLock算法其实本身是有一定的争议的,有大佬质疑该算法的可靠性;同时因为需要的机器过多,也会浪费资源,所以RedLock也不推荐使用。
zk分布式锁:
- 优点:zk本身其实就是CP的,能够保证加锁数据的一致性。每个节点的创建都会同时写入leader和follwer节点,半数以上写入成功才返回,如果leader节点挂了之后选举的流程会优先选举zxid(事务Id)最大的节点,就是选数据最全的,又因为半数写入的机制这样就不会导致丢数据
- 缺点:性能没有redis高
所以通过上面的对比可以看出,redis分布式锁和zk分布式锁的侧重点是不同的,这是redis和zk本身的定位决定的,redis分布式锁侧重高性能,zk分布式锁侧重高可靠性。所以一般项目中redis分布式锁和zk分布式锁的选择,是基于业务来决定的。如果你的业务需要保证加锁的可靠性,不能出错,那么zk分布式锁就比较符合你的要求;如果你的业务对于加锁的可靠性没有那么高的要求,那么redis分布式锁是个不错的选择。
最后,希望通过这两篇文章,让大家对于zookeeper分布式锁和redis分布式锁的实现有个更好的认识。
文章转自公众号:三友的java日记