分布式锁就是多台机器,分布在不一样的JVM中,这些不一样JVM内的方法须要获取一个惟一锁,好比获取锁以后要把数据写入数据库,保证数据在同一时刻只有一台机器写入数据库。java
分布式锁的实现有多种实现方法,除了今天聊到的ZK实现的分布式锁还有Redis经过SETNXPX或Lua脚本实现,还能够经过数据库的锁实现,但今天我们主要聊一下ZK的分布式锁的原理实现。git
zookeeper能够建立两种节点,一种是永久型的,一种是临时型还能够是有序的,当机器与zk失去链接的时候临时节点会自动删除,这个功能很是强大以致于不少功能都是基于此,好比leader选举等。如今直接上一张我本身画的图:github
首先会有一个永久节点\Locks,而后每一个客户端请求的时候会建立一个临时有序节点,在这时每一个都是有序的,最小的节点就意味着获取了锁。数据库
在此图上显然ClientC获取了锁,其余的锁获取的节点不是最小的,可是他们以前会有一个连接,就是lock_00000001在虽然没有获取锁,可是会须要监听lock_00000000的,由于若是监听全部节点的话会浪费不少的资源。相应的大的节点都会watch比本身小的节点,当比本身节点小的节点释放以后而后就能够继续处理了。分布式
咱们看看Curator很好的帮咱们实现了这样的功能,全部你们能够直接拿过来用: 测试
InterProcessMutex lock = new InterProcessMutex(client, lockPath); try { lock.acquire(seconds, TimeUnit.SECONDS); //do something } catch (Exception e) { logger.error("error", e); } finally { lock.release(); }
不少东西都为咱们封装好了,若是用原生zookeepr API须要写太多的行,而且须要考虑的点很是的多。我在网上也找了一个例子,本身改了一把,而后跑了没有什么问题, 由于不是本身写的,全部不贴出来了,有须要了自行下载: https://github.com/stonehqs/Demo/blob/master/ZookeeperLock.javaui
可是在这里边我能想到的还有一场景须要你们一块儿思考一下:spa
1. 若是ZK集群出问题了,如何处理?线程
2. 若是方法调用的太频繁,这样会出现链接ZK被拒绝,好比一个应用链接数超过60个。code
你们若是有更好的方案,能够给我留言讨论。
我能想到的第1点就是采用多个集群,好比两个集群,在写入数据的时候同时写入到两个集群中(保证数据一致),若是有一个群集中超过一半不能使用的时候,那么整个集群不能用了,这时能够切换到另外一个群集,保证访问的高可用。
关于第2点,每一个链接ZK群集的IP会被记录下来,这样一个IP链接ZK集群的最大默认数量60个,若是超过60个的话会被拒绝链接,防止DDOS攻击。因此在每一个应用的方法调用的时候须要加入synchronized关键字,这样每一个应用在同一时刻有一个线程在进行处理,其余的线程能够等待或者直接去作别的处理。还有另外一个方案就是调整这个数变大,这样也能够解决一下,可是若是调整的话还须要多作一些测试,保证这个数字是最佳的。
好了,有问题的能够给我留言。下期再见。