springboot-redis-redisson分布式锁

本文详细介绍了SpringBoot中使用Redisson实现分布式锁的原理和步骤,包括普通分布式锁、哨兵模式和集群模式的配置。内容涵盖Redis分布式锁的实现原理,如设置唯一ID、看门狗机制、可重入锁以及加锁和释放锁的代码实现。此外,还提供了完整的代码示例,包括依赖、配置、接口和测试。
摘要由CSDN通过智能技术生成


比较:redis很明显优于zookeeper;就分布式锁实现的健壮性而言,zookeeper很明显优于redis。如何选择,取决于你的业务!

一、Redis分布式锁实现原理

在这里插入图片描述

简介

Redis的4种部署架构有:

  • 单机模式;
  • 主从模式;
  • 哨兵模式;
  • 集群模式;

Redlock分布式锁在非单机模式下才有意义,单机模式下可以直接使用普通分布式锁。

因为RedLock的实现完全基于普通分布式锁;

RedLock加锁过程: 向所有节点发送 set key value ex time nx指令,只要过半节点set成功,就认为加锁成功。
RedLock释放锁过程: 向所有节点发送del指令;

因为RedLock操作多个节点,所以效率略有下降;但避免了网络分区产生的多锁同时存在的情况;

1.普通分布式锁

// 构造redisson实现分布式锁必要的Config
Config config = new Config();
config.useSingleServer().setAddress("1.9.1.0:5379").setPassword("123").setDatabase(0);
// 构造RedissonClient
RedissonClient redissonClient = Redisson.create(config);
// 设置锁定资源名称
RLock disLock = redissonClient.getLock("DISLOCK");
boolean isLock;
try {
   
    //尝试获取分布式锁
    isLock = disLock.tryLock(500, 15000, TimeUnit.MILLISECONDS);
    if (isLock) {
   
        //TODO if get lock success, do something;
        Thread.sleep(15000);
    }
} catch (Exception e) {
   
} finally {
   
    // 无论如何, 最后都要解锁
    disLock.unlock();
}

通过代码可知,经过Redisson的封装,实现Redis分布式锁非常方便,我们再看一下Redis中的value是啥,和前文分析一样,hash结构,key就是资源名称,field就是UUID+threadId,value就是重入值,在分布式锁时,这个值为1(Redisson还可以实现重入锁,那么这个值就取决于重入次数了):

172.29.1.180:5379> hgetall DISLOCK
1) "01a6d806-d282-4715-9bec-f51b9aa98110:1"
2) "1"

2.哨兵模式

即sentinel模式,实现代码和单机模式几乎一样,唯一的不同就是Config的构造:

Config config = new Config();
config.useSentinelServers().addSentinelAddress(
        "redis://127.0.0.1:26378","redis://127.0.0.1:26379", "redis://127.0.0.1:26380")
        .setMasterName("mymaster")
        .setPassword("a123456").setDatabase(0);
RedissonClient redissonClient = Redisson.create(config);
// 还可以getFairLock(), getReadWriteLock()
RLock redLock = redissonClient.getLock("REDLOCK_KEY");
boolean isLock;
try {
   
    isLock = redLock.tryLock();
    // 500ms拿不到锁, 就认为获取锁失败。10000ms即10s是锁失效时间。
    isLock = redLock.tryLock(500, 10000, TimeUnit.MILLISECONDS);
    if (isLock) {
   
        //TODO if get lock success, do something;
    }
} catch (Exception e) {
   
} finally {
   
    // 无论如何, 最后都要解锁
    redLock.unlock();
}

3.集群模式

集群模式构造Config如下:

Config config = new Config();
config.useClusterServers().addNodeAddress(
        "redis://127.0.0.1:6375","redis://127.0.0.1:6376", "redis://127.0.0.1:6377",
        "redis://127.0.0.1:6378","redis://127.0.0.1:6379", "redis://127.0.0.1:6380")
        .setPassword("123").setScanInterval(5000);
RedissonClient redissonClient = Redisson.create(config);
// 还可以getFairLock(), getReadWriteLock()
RLock redLock = redissonClient.getLock("REDLOCK_KEY");
boolean isLock;
try {
   
    isLock = redLock.tryLock();
    // 500ms拿不到锁, 就认为获取锁失败。10000ms即10s是锁失效时间。
    isLock = redLock.tryLock(500, 10000, TimeUnit.MILLISECONDS);
    if (isLock) {
   
        //TODO if get lock success, do something;
    }
} catch (Exception e) {
   
} finally {
   
    // 无论如何, 最后都要解锁
    redLock.unlock();
}

如果是多个没有关系的redis单机之间使用RedLock来做分布式锁
可以直接将各个单机的锁组成一个锁:

RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);

唯一ID

实现分布式锁的一个非常重要的点就是set的value要具有唯一性,redisson的value是怎样保证value的唯一性呢?答案是UUID+threadId。入口在redissonClient.getLock(“REDLOCK_KEY”),源码在Redisson.java和RedissonLock.java中:

protected final UUID id = UUID.randomUUID();
String getLockName(long threadId) {
   
    return id + ":" + threadId;
}

看门狗Watchdog

在这里插入图片描述
看门狗是客户端的行为,创建锁后每隔10秒帮你把key的超时时间设为30s这样的话,就算一直持有锁也不会出现key过期了,其他线程获取到锁的问题了。
lockWatchdogTimeout(监控锁的看门狗超时,单位:毫秒)
默认值:30000

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值