当前位置: 欣欣网 > 码农

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

2024-05-04码农

👉 欢迎 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 / 赠书福利

新项目: 仿小红书 (微服务架构)正在更新中... , 全栈前后端分离博客项目 2.0 版本完结啦, 演示链接 http://116.62.199.48/ 。全程手摸手,后端 + 前端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,直到项目上线。 目前已更新了255小节,累计39w+字,讲解图:1716张,还在持续爆肝中.. 后续还会上新更多项目,目标是将Java领域典型的项目都整一波,如秒杀系统, 在线商城, IM即时通讯,Spring Cloud Alibaba 等等,


  • 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 获取同一个对象锁:

    图片

    👉 欢迎 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 / 赠书福利

    新项目: 仿小红书 (微服务架构)正在更新中... , 全栈前后端分离博客项目 2.0 版本完结啦, 演示链接 http://116.62.199.48/ 。全程手摸手,后端 + 前端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,直到项目上线。 目前已更新了255小节,累计39w+字,讲解图:1716张,还在持续爆肝中.. 后续还会上新更多项目,目标是将Java领域典型的项目都整一波,如秒杀系统, 在线商城, IM即时通讯,Spring Cloud Alibaba 等等,


    1. 

    2. 

    3. 

    4. 

    最近面试BAT,整理一份面试资料Java面试BATJ通关手册,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。

    获取方式:点「在看」,关注公众号并回复 Java 领取,更多内容陆续奉上。

    PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下在看,加个星标,这样每次新文章推送才会第一时间出现在你的订阅列表里。

    「在看」支持小哈呀,谢谢啦