全新的分布式锁,几行代码搞定,简单且强大


  • Lock (string,int) 方法的使用
  • UnLock (string) 方法的使用
  • TryLock (string,int) 方法的使用

前言:分布式锁是分布式系统中一个极为重要的工具。目前有多种分布式锁的设计方案,比如借助 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 获取同一个对象锁:


相关推荐

  • 32 个 Python 实例彻底解析 f-String 格式化浮点数 004【推荐收藏】
  • 京东秒送售后系统退款业务重构心得
  • 【腾讯云 BI 数据分析可视化大赛】有奖征文活动
  • 今天,创业4周年。
  • 混元文生图大模型正式开源:15 亿参数、首个中文原生DiT架构、与腾讯现网版本完全一致!
  • 都2024年了,串口通信还在用TTL?
  • 10.1K Star零门槛上手音频转文字工具
  • React19 她来了,她来了,他带着礼物走来了
  • GPT-4o成全球网友新玩具,秒秒钟纸质原型转录初始HTML,网友:谷歌你是一点流量摊不上啊
  • 蚂蚁百灵大模型一号位:GPT-4o发布不意外,原生多模态方向已明
  • Ilya出走加剧OpenAI离职潮!RLHF作者Jan Leike同日辞职,超级对齐项目分崩离析
  • AI拉货挣钱,已经绕地球2500圈了
  • 字节跳动大模型首次全员亮相:一口气9个,价格低99%,没有参数规模和榜单分数
  • 告别3D高斯Splatting算法,带神经补偿的频谱剪枝高斯场SUNDAE开源了
  • 首个中文原生DiT架构!腾讯混元文生图大模型全面开源,免费商用
  • 谷歌反击:Project Astra正面硬刚GPT-4o、Veo对抗Sora、新版Gemini变革搜索
  • Ilya官宣离职,超级对齐负责人Jan直接辞职,OpenAI还是走散了
  • 大模型价格进入“厘”时代,豆包大模型定价每千tokens仅0.8厘
  • 使用VPN“翻墙”违法,为什么大部分人都没事?
  • 70岁洗发水之王,20亿卖了