基于zookeeper的分布式lock实现
背景
?继续上一篇文章:http://agapple.iteye.com/blog/1183972?,项目中需要对分布式任务进行调度,那对应的分布式lock实现在所难免。
?
?这一周,在基于BooleanMutex的基础上,实现了zookeeper的分布式锁,用于控制多进程+多线程的lock控制
?
算法可以预先看一下zookeeper的官方文档:?
?
http://zookeeper.apache.org/doc/trunk/recipes.htmllock操作过程:首先为一个lock场景,在zookeeper中指定对应的一个根节点,用于记录资源竞争的内容每个lock创建后,会lazy在zookeeper中创建一个node节点,表明对应的资源竞争标识。 (小技巧:node节点为EPHEMERAL_SEQUENTIAL,自增长的临时节点)进行lock操作时,获取对应lock根节点下的所有字节点,也即处于竞争中的资源标识按照Fair竞争的原则,按照对应的自增内容做排序,取出编号最小的一个节点做为lock的owner,判断自己的节点id是否就为owner id,如果是则返回,lock成功。如果自己非owner id,按照排序的结果找到序号比自己前一位的id,关注它锁释放的操作(也就是exist watcher),形成一个链式的触发过程。unlock操作过程:将自己id对应的节点删除即可,对应的下一个排队的节点就可以收到Watcher事件,从而被唤醒得到锁后退出?
代码相关说明:
?
?
测试代码:
?
?
升级版?实现了一个分布式lock后,可以解决多进程之间的同步问题,但设计多线程+多进程的lock控制需求,单jvm中每个线程都和zookeeper进行网络交互成本就有点高了,所以基于DistributedLock,实现了一个分布式二层锁。
?
大致原理就是ReentrantLock 和?DistributedLock的一个结合。
?
?
?单jvm的多线程竞争时,首先需要先拿到第一层的ReentrantLock的锁拿到锁之后这个线程再去和其他JVM的线程竞争锁,最后拿到之后锁之后就开始处理任务。锁的释放过程是一个反方向的操作,先释放DistributedLock,再释放ReentrantLock。?可以思考一下,如果先释放ReentrantLock,假如这个JVM?ReentrantLock竞争度比较高,一直其他JVM的锁竞争容易被饿死。
代码:最后其实再可以发散一下,实现一个分布式的read/write lock,也差不多就是这个理了。项目结束后,有时间可以写一下
?
大致思路:
?
竞争资源标示: ?read_自增id , write_自增id首先按照自增id进行排序,如果队列的前边都是read标识,对应的所有read都获得锁。如果队列的前边是write标识,第一个write节点获取锁watcher监听: read监听距离自己最近的一个write节点的exist,write监听距离自己最近的一个节点(read或者write节点)
?
?