侧边栏壁纸
博主头像
清如许博主等级

努力成长为一颗大树,一半洒落阴凉,一半沐浴阳光,非常沉默非常骄傲,从不依靠从不寻找

  • 累计撰写 80 篇文章
  • 累计创建 44 个标签
  • 累计收到 5 条评论

目 录CONTENT

文章目录

A004-分布式锁-使用手册.md

清如许
2022-08-05 / 0 评论 / 0 点赞 / 8 阅读 / 1,235 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-08-05,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

| --- | --- | --- |
| 更新日期 | 2022年04月21日 | 作 者 | 张留杨 |
| 保密等级 | C | 开放范围 | 研发测试部 |

版本历史

版 本更新日期作 者备注
1.0.02022年04月21日张留杨新建文档

基于Redisson实现的分布式锁。

1. 支持功能

  • 服务器类型
  •  单点
  •  集群
  •  哨兵
  •  主从
  • 锁类型
  •  可重入锁(默认)
  •  公平锁
  •  读锁
  •  写锁
  • 锁颗粒度
  •  方法级别
  •  参数级别
  •  行代码级别
  • 使用方式
  •  声明式
  •  编程式

2. 版本记录

  • **1.0.0-SANPSHOT**
    支持分布式锁功能

3. 使用示例

global-lock-example

4. 快速开始

4.1 引入依赖

<dependency>
  <groupId>com.dindo</groupId>
  <artifactId>global-lock</artifactId>
  <version>1.0.0-SNAPSHOT</version>
</dependency>

4.2 配置文件

dindo:
  global-lock:
    address: redis://192.168.88.200:6389
    password: 123456

更多配置:

dindo:
  global-lock:
    address: redis://192.168.88.200:6389
    password: 123456
    codec: org.redisson.codec.JsonJacksonCodec
    database: 15
    lease-time: 60
    wait-time: 60
    prefix: dindo.global-lock
    pool:
      size: 20
      min-idle: 1
      idle-timeout: 60000
      command-timeout: 500
      connection-timeout: 30000
    cluster:
      nodes:
        - redis://192.168.88.200:6379
        - redis://192.168.88.200:6389
        - redis://192.168.88.200:6399
    sentinel:
      master: mymaster
      nodes:
        - redis://192.168.88.200:6379
        - redis://192.168.88.200:6389
        - redis://192.168.88.200:6399
    master-slave:
      master: redis://192.168.88.200:6379
      slaves:
        - redis://192.168.88.200:6379
        - redis://192.168.88.200:6389
        - redis://192.168.88.200:6399

特别说明:

  • 无特别需求只需配置addresspassword即可
  • 目前集群、哨兵、主从模式由于部署对应模式,暂无验证

4.3 声明式

使用方式就是在方法上添加@GlobalLock的注解即可,其中各个参数说明如下:

  • name 锁名称
    • 如果不指定name参数,那么生成的rediskey为"${dindo.global-lock.prefix}:包名.方法名-参数"
    • 如果指定name参数,那么生成的rediskey为"${dindo.global-lock.prefix}:name-参数"
  • keys 自定义的业务key,也就是可以根据业务参数进行加锁
  • lockType 锁类型,默认可重入锁(LockType.REENTRANT
  • waitTime 获取锁的等待时长(默认为Long.MIN_VALUE
  • leaseTime 上锁以后多少秒自动解锁(默认为Long.MIN_VALUE
  • lockTimeoutStrategy 获取锁超时时执行的策略,默认为任何动作也不做,直接执行业务逻辑。
    强烈建议使用LockTimeoutStrategy.FAST_FAIL,即获取锁失败抛异常
  • customLockTimeoutStrategy 自定义的获取锁超时执行的策略
  • releaseTimeoutStrategy 释放锁时已超时的处理策略,同样默认情况下任何动作也不执行
  • customReleaseTimeoutStrategy 自定义释放锁时已超时的处理策略

4.3.1 锁定单业务key

import com.dindo.globallock.annotation.GlobalLock;
import com.dindo.globallock.enums.LockTimeoutStrategy;

@GetMapping("useSingleKeyLock/{name}")
@GlobalLock(keys = "#name", leaseTime = 2, lockTimeoutStrategy = LockTimeoutStrategy.FAST_FAIL)
public String useSingleKeyLock(@PathVariable String name){
        return"success";
        }

4.3.2 锁定多业务key

import com.dindo.globallock.annotation.GlobalLock;
import com.dindo.globallock.enums.LockTimeoutStrategy;

@GetMapping("useMultiKeyLock/{name}")
@GlobalLock(keys = {"#name", "'hello'"}, leaseTime = 2, lockTimeoutStrategy = LockTimeoutStrategy.FAST_FAIL)
public String useMultiKeyLock(@PathVariable String name){
        return"success";
        }


@GetMapping("useSingleKeyLock2")
@GlobalLock(keys = {"#name1", "name2"}, leaseTime = 2, lockTimeoutStrategy = LockTimeoutStrategy.FAST_FAIL)
public String useMultiKeyLock(String name1,String name2){
        return"success";
        }


@GetMapping("useSingleKeyLock3")
@GlobalLock(keys = {"#user.name", "user.age"}, leaseTime = 2, lockTimeoutStrategy = LockTimeoutStrategy.FAST_FAIL)
public String useMultiKeyLock(User user){
        return"success";
        }

static class User {
  String name;
  Integer age;
}

4.3.3 注解锁定

import com.dindo.globallock.annotation.GlobalLock;
import com.dindo.globallock.annotation.LockKey;
import com.dindo.globallock.enums.LockTimeoutStrategy;

@GetMapping("useAnnotationKeyLock/{name}/{age}")
@GlobalLock(leaseTime = 2, lockTimeoutStrategy = LockTimeoutStrategy.FAST_FAIL)
public String useAnnotationKeyLock(@PathVariable("name") @LockKey String name,@PathVariable("age") @LockKey Integer age){
        return"success";
        }

4.3.4 指定key前缀

import com.dindo.globallock.annotation.GlobalLock;
import com.dindo.globallock.annotation.LockKey;
import com.dindo.globallock.enums.LockTimeoutStrategy;


@GetMapping("usePrefixLock")
@GlobalLock(name = "usePrefixLock", lockTimeoutStrategy = LockTimeoutStrategy.FAST_FAIL)
public String usePrefixLock(@LockKey String name){
        return"success";
        }

4.4 编程式

import com.dindo.globallock.provider.LockProvider;
import com.dindo.globallock.enums.LockType;

@Resource
private LockProvider lockProvider;

@GetMapping("useProgrammaticallyLock")
public void useProgrammaticallyLock()throws Exception{

        String lock=lockProvider.lock("useProgrammaticallyLock",LockType.REENTRANT,()->{

        ThreadUtil.sleep(5,TimeUnit.SECONDS);

        return"success";

        });

        System.out.println(lock);
        }

重载方法:

public interface LockProvider {

  /**
   * 加锁
   *
   * @param lockName       锁名称
   * @param businessWorker 要执行的业务逻辑
   * @return {@link T}
   * @throws Exception 异常
   */
  default <T> T lock(String lockName, AcquiredLockWorker<T> businessWorker) throws Exception {
    return this.lock(lockName, LockType.REENTRANT, businessWorker, 60, 60);
  }

  /**
   * 加锁
   *
   * @param lockName       锁名称
   * @param businessWorker 要执行的业务逻辑
   * @param waitTime       等待时间
   * @param leaseTime      租赁时间
   * @return {@link T}
   * @throws Exception 异常
   */
  default <T> T lock(String lockName, AcquiredLockWorker<T> businessWorker, long waitTime, long leaseTime) throws Exception {
    return this.lock(lockName, LockType.REENTRANT, businessWorker, waitTime, leaseTime);
  }

  /**
   * 加锁
   *
   * @param lockName       锁名称
   * @param lockType       锁类型
   * @param businessWorker 要执行的业务逻辑
   * @return {@link T}
   * @throws Exception 异常
   */
  default <T> T lock(String lockName, LockType lockType, AcquiredLockWorker<T> businessWorker) throws Exception {
    return this.lock(lockName, lockType, businessWorker, 60, 60);
  }

  /**
   * 加锁
   *
   * @param lockName       锁名称
   * @param lockType       锁类型
   * @param businessWorker 要执行的业务逻辑
   * @param waitTime       等待时间
   * @param leaseTime      租赁时间
   * @return {@link T}
   * @throws Exception 异常
   */
  <T> T lock(String lockName, LockType lockType, AcquiredLockWorker<T> businessWorker, long waitTime, long leaseTime) throws Exception;

}
0

评论区