redisson 分布式锁

分布式锁的基本特点:互斥,防死锁,性能,可重入
针对以上特点,Redisson都能做到很好的满足。

先看demo效果

pom依赖

<!-- redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.7.4</version>
</dependency>

配置文件

spring:
  redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    password:
    pool:
      max-active: 10
      max-wait: -1
      max-idle: 8
      min-idle: 0
    imeout: 0

config配置

/**
 * @author TangHaiZhi
 * @date 2021/7/22
 */
@Configuration
public class RedissonConfig {

    @Bean
    public RedissonClient redissonClient(){
        Config config = new Config();
        config.useSingleServer()
                .setAddress("redis://127.0.0.1:6379");
        RedissonClient redisson = Redisson.create(config);
        return redisson;
    }

}

未加锁时

用Jmeter在5秒内并发6000次,可以看到消费时又很多次都重复消费了
在这里插入图片描述

对代码进行改造,用redisson进行加锁

@Autowired
RedissonClient redissonClient;

@RequestMapping(value = "/consumer", method = RequestMethod.GET)
public String consumer() {
    RLock lock = redissonClient.getLock("LOCKKEY");
    try {
    	//这里的5指有5s的时间争抢锁,5s后为抢到锁返回false
        boolean flag = lock.tryLock(5,TimeUnit.SECONDS);
        if (flag){
            List<ServHwMerchant> list = servHwMerchantDAO.findAll();
            int num = list.get(0).getIndustry();
            num--;
            System.out.println("num=" + num);
            list.get(0).setIndustry(num);
            servHwMerchantDAO.save(list.get(0));
            return "success";
        } else {
            return "fail";
        }
    } catch (Exception e){
        System.out.println(e.getMessage());
    }finally {
        lock.unlock();
    }
    return "fail";
}

加锁后

用Jmeter在5秒内并发6000次,可以看到没有出现重复消费的情况了
在这里插入图片描述

深入分析

上面有说到Redission对互斥,防死锁,性能,可重入都有很好的满足。
互斥很好理解,当有一个线程获得锁之后别的线程拿不到锁,就一直循环等待锁。

防死锁,我们在加锁之后,redisson会自动设置一个锁的有效时间,到期之后redisson会自动释放锁。
那么这里就出现了几个问题
问题:如果到期之后我的业务逻辑其实还没有走完,这个时候redisson给我自动释放锁了怎么办。(默认30s后自动释放锁
这里就要另外再说一个东西,redisson的看门狗。它的作用是在Redisson实例被关闭前,不断的延长锁的有效期,也就是说,如果一个拿到锁的线程一直没有完成逻辑,那么看门狗会帮助线程不断的延长锁超时时间,锁不会因为超时而被释放。
这里博主自己做过尝试,获取到锁后直接将线程sleep40秒,然后用redis的可视化工具观察锁的生存时间,发现获取到锁后是30,当生存时间减少到20时,看门狗启动了,将生存时间重置为30.也就是说不是20+30=50.
默认情况下,看门狗的续期时间是30s,也可以通过修改Config.lockWatchdogTimeout来另行指定。如下图所示:
在这里插入图片描述
再了解一下另一个tryLock方法
tryLock(long waitTime, long leaseTime, TimeUnit unit)

  • waitTime 为获取锁的最大等待时间
  • leaseTime 为多久之后制动释放锁
  • unit 为锁的时间级别
    指定leaseTime参数的加锁方法来指定加锁的时间。超过这个时间后锁便自动解开了,不会延长锁的有效期。因此最好不要使用这个方法。
    另外在finally中必须释放锁,否则会出现业务报错后的死锁情况。

缺陷

redis在哨兵模式下,在master挂掉的情况下,会将一个备用节点切换为master。如果是在master上加了锁,还没有同步到备用节点上的时候挂了,这时候将备用节点切换过来。就会出现问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值