最简单分布式锁ZK实现方案

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介:

分布式锁简单封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package  com.hellojd.cloud.locks.v1;
import  org.apache.zookeeper.*;
import  java.io.IOException;
import  java.util.concurrent.CountDownLatch;
import  static  org.apache.zookeeper.Watcher.Event.KeeperState.SyncConnected;
 
/**
  * 最简单分布式锁实现方案
  */
public  class  ZookerSession  implements  Watcher {
     private  CountDownLatch countDownLatch= new  CountDownLatch( 1 );
     private  ZooKeeper zooKeeper;
     private  static   class   Singleton{
         private   static   ZookerSession instance;
         static  {
             instance =  new  ZookerSession();
         }
 
         public  static  ZookerSession getInstance(){
             return  instance;
         }
     }
     public  static  ZookerSession getInstance(){
         return  Singleton.getInstance();
     }
 
 
     public  ZookerSession() {
         try  {
             this .zooKeeper =  new  ZooKeeper( "192.168.0.10:2181" , 50000 , this );
             countDownLatch.await();
             System.out.println( "state:  " +zooKeeper.getState());
             System.out.println( "connection estalished!!" );
         catch  (IOException e) {
             e.printStackTrace();
         catch  (InterruptedException e) {
             e.printStackTrace();
         }
     }
     public  ZooKeeper getZooKeeper(){ return  this .zooKeeper;}
     @Override
     public  void  process(WatchedEvent event) {
         if (event.getState()==SyncConnected){
             countDownLatch.countDown();
         }
     }
     public  void  releaseDistributeLock(Long id){
         String path = "/lock_" +id;
         try  {
             zooKeeper.delete(path,- 1 );
         catch  (InterruptedException e) {
             e.printStackTrace();
         catch  (KeeperException e) {
             e.printStackTrace();
         }
     }
 
     public  void  acquireDistributeLock(Long id){
         String path = "/lock_" +id;
         try  {
             zooKeeper.create(path, null , ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
//            System.out.println("success to acquire lock "+id);
         catch  (KeeperException e) {
             //没有获取到锁
             int  count= 0 ;
             while  ( true ){
                 try {
                     Thread.sleep( 200 );
                     zooKeeper.create(path, null , ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
                 } catch  (InterruptedException e1) {
                     count++;
                     continue ;
                 catch  (KeeperException e1) {
//                    e1.printStackTrace();
                     count++;
                     continue ;
                 }
//                System.out.println("success to acquire lock "+id);
                 break ;
             }
 
         catch  (InterruptedException e) {
             e.printStackTrace();
         }
     }
 
}


2.测试线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package  com.hellojd.cloud.locks.v1;
 
import  org.apache.zookeeper.CreateMode;
import  org.apache.zookeeper.KeeperException;
import  org.apache.zookeeper.ZooDefs;
import  org.apache.zookeeper.data.Stat;
 
/**
  * 测试线程
  */
public  class  Task  implements   Runnable {
     private  int  loop;
     private  Long lockid;
     ZookerSession zs;
     public  Task( int  loop,Long lockid) {
         zs = ZookerSession.getInstance();
         this .loop = loop;
         this .lockid = lockid;
     }
 
     @Override
     public  void  run() {
 
         ZookerSession.getInstance().acquireDistributeLock(lockid);
         for ( int  i= 0 ;i<loop;i++){
             int  count = getcount();
             System.out.println(Thread.currentThread().getName()+ "-->" +count);
             count(++count);
         }
         zs.releaseDistributeLock(lockid);
     }
     //计数
     public  void  count( int  count){
         try  {
             Stat s = zs.getZooKeeper().exists( "/count" false );
             if (s== null ){
                 System.out.println( "count 不存在" );
                 zs.getZooKeeper().create( "/count" ,String.valueOf(count).getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
             } else {
                 zs.getZooKeeper().setData( "/count" ,String.valueOf(count).getBytes(),- 1 );
             }
         catch  (KeeperException e) {
             e.printStackTrace();
         catch  (InterruptedException e) {
             e.printStackTrace();
         }
     }
     public  int  getcount(){
         try  {
             Stat s = zs.getZooKeeper().exists( "/count" false );
             if (s== null ){
                 zs.getZooKeeper().create( "/count" ,String.valueOf( 0 ).getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                 return  0 ;
             } else {
                 byte [] data = zs.getZooKeeper().getData( "/count" false null );
                 return  Integer.valueOf( new  String(data));
             }
         catch  (KeeperException e) {
             e.printStackTrace();
         catch  (InterruptedException e) {
             e.printStackTrace();
         }
         return  - 1 ;
     }
     public  static  void  main(String[] args) {
         long  LOCKID = 2l;
         for ( int  i= 0 ;i< 100 ;i++){
             new  Thread( new  Task( 1 , LOCKID)).start();
         }
     }
}



原理:分布式锁通过死循环+实现等待效果。如果线程可以创建节点,则成功获取锁;

释放锁:就是将数据节点在ZK上删除。


缺点:简单且性能低。有风险。如果获取锁的线程中断,导致任务异常。




本文转自 randy_shandong 51CTO博客,原文链接:http://blog.51cto.com/dba10g/1975120,如需转载请自行联系原作者
相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
相关文章
|
NoSQL 安全 Redis
Redis 分布式锁实现方案
Redis 分布式锁实现方案
4789 4
|
5月前
|
NoSQL 算法 Java
(十三)全面理解并发编程之分布式架构下Redis、ZK分布式锁的前世今生
本文探讨了从单体架构下的锁机制到分布式架构下的线程安全问题,并详细分析了分布式锁的实现原理和过程。
110 6
|
4月前
|
消息中间件 存储 C#
分布式事务之最终一致性实现方案
分布式事务之最终一致性实现方案
87 0
|
算法 NoSQL 关系型数据库
分布式系统第三讲:全局唯一ID实现方案
分布式系统第三讲:全局唯一ID实现方案
426 0
|
7月前
|
监控 安全 Apache
Apache ZooKeeper - 使用ZK实现分布式锁(非公平锁/公平锁/共享锁 )
Apache ZooKeeper - 使用ZK实现分布式锁(非公平锁/公平锁/共享锁 )
342 1
|
7月前
|
NoSQL Java 应用服务中间件
2024年面试复盘大全500道:Redis+ZK+Nginx+数据库+分布式+微服务
今天分享给大家的都是目前主流企业使用最高频的面试题库,也都是 Java 版本升级之后,重新整理归纳的最新答案,会让面试者少走很多不必要的弯路。同时每个专题都做到了详尽的面试解析文档,以确保每个阶段的读者都能看得懂,同时这部分面试文档也是可以免费的提供给有需要的同学们学习的
|
消息中间件 Java 关系型数据库
分布式系统第五讲:分布式事务及实现方案
分布式系统第五讲:分布式事务及实现方案
181 0
|
缓存 SpringCloudAlibaba 监控
Spring Boot项目分布式锁实现方案:Redisson
`Redisson`是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。其中包括(`BitSet`, `Set`, `Multimap`, `SortedSet`, `Map`, `List`, `Queue`, `BlockingQueue`, `Deque`, `BlockingDeque`, `Semaphore`, `Lock`, `AtomicLong`, `CountDownLatch`, `Publish / Subscribe`, `Bloom filter`,
704 0
Spring Boot项目分布式锁实现方案:Redisson
|
SQL 负载均衡 NoSQL
【防止重复下单】分布式系统接口幂等性实现方案
【防止重复下单】分布式系统接口幂等性实现方案
1766 0
【防止重复下单】分布式系统接口幂等性实现方案
|
NoSQL 算法 中间件
分布式锁的 3 种实现方案
分布式锁的 3 种实现方案
211 0