Zookeeper 分布式锁
什么是分布式锁?
在进行分布式锁操作之前,我们得知道什么是分布式锁。在单体应用中,使用 API 自带的 javaLock 或者是 synchronize 就可以解决线程多带来的并发问题。但是在集群环境
中,上述的方法并不能解决服务与服务之间的并发问题。
分布式锁一般用在分布式系统或者多个应用中,用来控制同一任务是否执行或者任务的执行顺序。在项目中,部署了多了应用,在执行定时任务时就会遇到同一任务可能执行多次的情况,我们可以借助分布式锁,保证在同一时间只有一个tomcat应用执行了定时任务
实现分布式锁的方式
- 数据库实现(效率低,不推荐)
- redis 实现(使用 redission 实现,当需要考虑死锁和释放问题,比较繁琐)
- Zookeeper 实现(使用临时节点,效率高)
- spring Cloud 实现全局锁(内置的)
Zookeeper 实现分布式锁
实现原理
使用 Zookeeper 创建临时顺序节点,判断自己是不是当前节点下的最小节点
,是的话就是获取到了锁,直接执行业务代码。不是的话,便对前一个节点进行监听。获取到锁,执行完业务代码后,delete 节点释放当前锁,然后下面的节点接收到通知。
案例实战
原生 Zookeeper 案例
编写分布式锁的代码
public class DistributedLock { private final String connectString = "192.168.3.33:2181"; private final int Timeout = 2000; private final ZooKeeper zooKeeper; private final String rootNode = "locks"; private final String subNode = "seq-"; private CountDownLatch connectLatch = new CountDownLatch(1); private CountDownLatch waitLatch = new CountDownLatch(1); private String waitPath; private String currentNode; public DistributedLock() throws IOException, KeeperException, InterruptedException { // 获取连接 zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() { @Override public void process(WatchedEvent event) { // 连接建立时, 打开 latch, 唤醒 wait 在该 latch 上的线程 if (event.getState() == Event.KeeperState.SyncConnected) { connectLatch.countDown(); } // 发生了 waitPath 的删除事件 if (eve