redis: redisson实现分布式锁、限流、防重提交,依赖即可使用的注解工具

项目开源地址

快速开始

<dependency>
    <groupId>io.github.smilexizheng</groupId>
    <artifactId>redisson-tool-spring-boot-starter</artifactId>
    <version>1.0.1</version>
</dependency>

组件已经发布到maven中央仓库,最新版本的依赖

项目配置
#redisson工具
redisson-tool:
  #启用功能
  enabled: true
  #redisson配置文件
  path: lock/redisson-lock.yml
  #分布式锁
  lock-enabled: true
  #限流
  rate-limiter-enabled: true
  #防重提交
  repeat-submit-enabled: true

lock/redisson-lock.yml 参考redisson的声明式配置

---
singleServerConfig:
  idleConnectionTimeout: 10000
  connectTimeout: 10000
  timeout: 3000
  retryAttempts: 3
  retryInterval: 1500
  password: 123456789
  subscriptionsPerConnection: 5
  clientName: mainRedis
  address: "redis://127.0.0.1:6379"
  subscriptionConnectionMinimumIdleSize: 1
  subscriptionConnectionPoolSize: 50
  connectionMinimumIdleSize: 24
  connectionPoolSize: 64
  database: 6
  dnsMonitoringInterval: 5000
threads: 16
nettyThreads: 32
codec: !<org.redisson.codec.Kryo5Codec> { }
transportMode: "NIO"

分布式锁

//最小化使用
@RedissonLock
public String get(String userId){
        return "helloWorld"+userId;
}

//完整配置
@RedissonLock(value = "lockKey", param = "#userId", waitTime = 10, leaseTime = 30, type = LockType.FAIR, timeUnit = TimeUnit.SECONDS)
public String get(String userId){
        return "helloWorld"+userId;
}


//编程式使用
@Autowired 
private LockClient lockClient;

public String get(String userId) {  
    String key = "user:"+userId;
    String data= lockClient.lock(key, LockType.FAIR,10,20, TimeUnit.SECONDS,()->{               
          return "hello"+key;
        });
    return data;
}

  • value:key 默认空,可不填
  • param: key的二级参数 支持spel,默认空
  • waitTime: 等待时间,默认 30
  • leaseTime: 自定解锁时间 默认60
  • timeUnit:时间单位 默认秒
  • type: 公平锁/普通锁 默认公平锁

限流器

//最小化使用
@RateLimiter
public String get(String userId){
        return "helloWorld"+userId;
}

//完整配置
@RateLimiter(value="getUserInfo",param = "#userId",rate = 100,rateInterval = 1 ,timeUnit = TimeUnit.MINUTES)
public String get(String userId){
        return "helloWorld"+userId;
}
  • value:key 默认空,可不填
  • param: key的二级参数 支持spel,默认空
  • rate: 等待时间,默认 100
  • rateInterval: 自定解锁时间 默认 1
  • timeUnit:时间单位 默认 分钟

防重提交

//最小化使用
@RepeatSubmit
public String get(String userId){
        return "helloWorld"+userId;
}

//完整配置
@RepeatSubmit(value="getUserInfo",param = "#userId",expireTime = 10,waitExpire = true,validateForm=true,timeUnit = TimeUnit.SECONDS)
public String get(String userId){
        return "helloWorld"+userId;
}
  • value:key 默认空,可不填
  • param: key的二级参数 支持spel,默认空
  • expireTime: 等待时间,默认 10
  • waitExpire: true 等待时间自动过期, false 执行完立即过期。默认true
  • timeUnit:时间单位 默认 分钟
  • validateForm: 是否校验表单 默认true

三、 配置说明

3.1 key的自动生成
  • value 作为key使用,默认空可不填,使用切入方法的JoinPoint.StaticPart转hex 作为key
  • param 作为粒度控制,比如某用户,某类型,支持spel
3.2 混合使用的处理次序
    
    @RedissonLock
    @RepeatSubmit
    @RateLimiter
    public String get(String key) {
        return "hello";
    }
  • 使用@Order控制切面执行顺序
  • 1.@RepeatSubmit 防重提交
  • 2.@RateLimiter 限流器
  • 3.@RedissonLock 分布式锁

四、捕获异常 响应式处理

创建异常处理类 GlobalExceptionHandler,可进行错误日志记录,正确返回错误信息。
参考:

/**
 * 自定义异常处理
 */
@ControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(value = RedissonToolException.class)
    @ResponseBody
    public R rateLimiterExceptionHandler(RedissonToolException e,HttpServletRequest req){
        logger.error(String.format("[%s]%s:%s",req.getRequestURL().toString(),e.getType().toString(),e.getMessage()));
        String errorMsg;
        switch (e.getType()){
            case TryLockFail:
                errorMsg = "排队中,请重试";
                break;
            case RateLimiterException:
                errorMsg ="系统繁忙,请重试!";
                break;
            case RepeatException:
                errorMsg ="请勿重复提交!";
                break;
//          更多异常见 org.smilexizheng.exception.ExceptionType 
            default:
                errorMsg ="系统繁忙!";
                break;
        }
        return R.error(errorMsg);
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Redisson实现分布式锁可以确保在分布式环境中对共享资源的访问是互斥的。下面是使用Redisson实现分布式锁的步骤: 1. 添加Redisson依赖:在`pom.xml`文件中添加Redisson依赖。 ```xml <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.15.5</version> </dependency> ``` 2. 配置Redisson连接信息:在`application.properties`文件中配置Redis连接信息。 ```properties spring.redis.host=127.0.0.1 spring.redis.port=6379 ``` 3. 创建RedissonClient Bean:在配置类中创建RedissonClient Bean,用于获取分布式锁实例。 ```java @Configuration public class RedissonConfig { @Value("${spring.redis.host}") private String redisHost; @Value("${spring.redis.port}") private String redisPort; @Bean(destroyMethod = "shutdown") public RedissonClient redissonClient() { Config config = new Config(); config.useSingleServer().setAddress("redis://" + redisHost + ":" + redisPort); return Redisson.create(config); } } ``` 4. 使用分布式锁:在需要进行互斥访问的代码块中使用分布式锁。 ```java @Autowired private RedissonClient redissonClient; public void doSomething() { RLock lock = redissonClient.getLock("myLock"); try { // 尝试获取锁,等待10秒,锁自动释放时间为30秒 boolean isLocked = lock.tryLock(10, 30, TimeUnit.SECONDS); if (isLocked) { // 获得锁之后执行业务逻辑 // ... } else { // 获取锁失败,处理异常情况 // ... } } catch (InterruptedException e) { // 处理异常 // ... } finally { // 释放锁 lock.unlock(); } } ``` 在以上示例中,我们使用Redisson的RLock对象来获取分布式锁使用`tryLock`方法可以尝试获取锁,如果获取成功,则执行相应的业务逻辑;如果获取失败,则根据实际情况处理异常。最后,使用`unlock`方法释放锁。 通过以上步骤,就可以使用Redisson实现分布式锁,确保在分布式环境中对共享资源的互斥访问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值