关于分布式锁:全新的分布式锁功能简单且强大

99次阅读

共计 2692 个字符,预计需要花费 7 分钟才能阅读完成。

起源:《全新的分布式锁,性能简略且弱小》
前言:分布式锁是分布式系统中一个极为重要的工具。目前有多种分布式锁的设计方案,比方借助 redis,mq,数据库,zookeeper 等第三方服务零碎来设计分布式锁。tldb 提供的分布式锁,次要是要简化这个设计的过程,提供一个简洁牢靠,相似应用程序中对象锁的形式来获取分布式锁。

tldb 提供分布式锁应用办法:

  1. lock 阻塞式申请锁
  2. trylock 尝试加锁,若锁已被占用,则失败返回,反之,则获取该锁
  3. unlock 开释曾经获取的锁

    tldb 提供的分布式锁性能次要在 MQ 模块中实现,调用的办法在 MQ 客户端实现,客户端的实现理论非常简单,除了目前曾经实现的几种语言 java,golang,python,javaScript 写的 simpleClient,其实其余开发者有趣味也能够实现其余语言的 MQ 客户端,齐全没有技术门槛。分布式锁由 tldb 服务器管制,所以它绝对客户端来说,也是跨语言的,如,用 java 客户端上锁的对象,其余语言同样无奈获取该对象锁。


Lock(string,int) 办法的应用

tldb 提供的是以字符串为锁对象的独占锁,如,lock(“abc”,3) 必须提供两个参数:

  1. 第一个参数为锁对象,即服务器对“abc”对象调配一个锁,所有对 ”abc” 对象申请加锁的线程争用一个独占锁,该办法为一个阻塞办法,申请到锁则返回,如果锁被其余线程占用,则始终阻塞直至获取到锁。
  2. 第二个参数为持有该分布式锁的最长工夫,单位为秒,例如 lock(“abc”,3),意思是,如果超过 3 秒还没有调用 unlock 开释该锁,服务器将强制开释该锁,持续将锁调配给其余申请的线程。

UnLock(string) 办法的应用

  • UnLock 为开释分布式锁时调用的办法。客户端在胜利获取分布式锁后,服务器会返回一个该锁的 key,客户端执行完逻辑代码的最初,必须显式调用 UnLock(key) 来开释该分布式锁。如果没有调用 unlock 开释锁,tldb 将期待锁开释的超时工夫直至超时后强制开释该锁。

TryLock(string,int) 办法的应用

  • trylock 与 lock 类似,然而 lock 办法阻塞的,调用 lock 办法申请分布式锁时,如果该锁曾经被占用,那么 lock 办法将始终期待直至 tldb 服务器将锁调配给它,这与程序中获取独占锁的形式统一。而 trylock 时非阻塞的,调用 trylock 后会立刻返回,如果获取到锁,tldb 会将标识该锁的 key 一并返回,如何该锁曾经被占用,服务器将返回空数据。

以下以 go 为例应用分布式锁

因为 tldb 分布式的实现是在 MQ 模块,所以 go 程序必须应用 tlmq-go, tldb 的 mq 客户端进行调用锁办法。

   import  "github.com/donnie4w/tlmq-go/cli"

调用 lock 的程序:lock 办法是阻塞的

sc := cli.NewMqClient("ws://127.0.0.1:5001", "mymq=123")
sc.Connect()
// 以上为 客户端连贯 MQ 服务器

key, err := sc.Lock("testlock", 3)
//lock 中两个参数,第一个参数为字符串,即 tldb 服务器为“testlock”调配一个全局的分布式锁
// 第二个参数 3 为客户端持有该锁的最长工夫,示意超过 3 秒没有开释锁时,tldb 服务器将在服务端强制开释该锁,并调配给其余申请锁的线程

if err!=nil{// 获取锁失败,需查看 tldb 能失常拜访}else{defer sc.UnLock(key) // 获取锁胜利后,必须在程序最初调用 Unlock
    // 执行业务逻辑程序
}  

调用 tryLock 的程序,trylock 是非阻塞的

sc := cli.NewMqClient("ws://127.0.0.1:5001", "mymq=123")
sc.Connect()  

if key, ok := sc.TryLock("testlock2", 3); ok {
    //ok 为 true,示意曾经胜利获取到分布式锁
    defer sc.UnLock(key) // 在程序最初开释锁对象
    ...        
}

go 用自旋的形式应用 trylock 获取分布式锁,实现程序的阻塞期待

sc := cli.NewMqClient("ws://127.0.0.1:5001", "mymq=123")
sc.Connect()
var key string
for {if  v, ok := sc.TryLock("testlock", 3); ok {
        key = v
        break
    } else {<-time.After(100* time.Millisecond)
    }
}
defer sc.UnLock(key)
...// 业务逻辑代码 

这段程序应该比拟易于了解,就是每隔 100 毫秒,循环获取字符串“testlock”的分布式锁直至胜利。


以下以 java 为例
java 客户端为 tlmq-j:https://github.com/donnie4w/tlmq-j

maven 配置

<dependency>        
   <groupId>io.github.donnie4w</groupId>      
   <artifactId>tlmq-j</artifactId>     
   <version>0.0.2</version>   
</dependency>

调用 lock 办法

MqClient mc = new SimpleClient("ws://127.0.0.1:5001", "mymq=123");
mc.connect();
//java 连贯服务器
String key = null;
try{key = mc.lock("testlock", 3); // 获取分布式
      
      ... // 执行业务逻辑程序
}finally {if (key!=null){mc.unLock(key); // 开释分布式锁
     }               
}

调用 trylock 办法

MqClient mc = new SimpleClient("ws://127.0.0.1:5001", "mymq=123");
mc.connect();
String key = null;
try{key = mc.tryLock("testlock", 3); // 获取分布式
      
      ... // 执行业务逻辑程序
} finally {if (key!=null){mc.unLock(key); // 开释分布式锁
     }               
}

以下是 tldb 分布式锁的性能测试数据:
多线程并发 调用 lock 获取同一个对象锁后,程序的运行数据:

多线程并发应用自旋的形式调用 trylock 与 lock 获取同一个对象锁:


有任何问题或倡议请 Email:donnie4w@gmail.com 或 https://tlnet.top/contact 发信给我,谢谢!

正文完
 0