请选择 进入手机版 | 继续访问电脑版

[Redis] Redisson实现Redis分布式锁的几种方式

  [复制链接]
查看368 | 回复93 | 2021-9-13 23:19:17 | 显示全部楼层 |阅读模式
目次

前几天发的一篇文章《Redlock:Redis分布式锁最牛逼的实现》,引起了一些同砚 的讨论,也有一些同砚 提出了一些疑问,这是好事儿。本文在讲解怎样 利用 Redisson实现Redis平常 分布式锁,以及Redlock算法分布式锁的几种方式的同时,也附带解答这些同砚 的一些疑问。

Redis几种架构

Redis发展到如今 ,几种常见的部署架构有:

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

我们起首 基于这些架构讲解Redisson平常 分布式锁实现,必要 注意 的是,只有充分相识 平常 分布式锁是怎样 实现的,才能更好的相识 Redlock分布式锁的实现,由于 Redlock分布式锁的实现完全基于平常 分布式锁。

平常 分布式锁

Redis平常 分布式锁这个大家基本上只相识 ,本文不打算过多的先容 ,上一篇文章《Redlock:Redis分布式锁最牛逼的实现》也讲的很细,并且也说到了几个告急 的注意 点。

以是 直接show you the code,毕竟talk is cheap。

redisson版本

本次测试选择redisson 2.14.1版本。

单机模式

源码如下:

  1. // 构造redisson实现分布式锁必要的Config
  2. Config config = new Config();
  3. config.useSingleServer().setAddress("redis://172.29.1.180:5379").setPassword("a123456").setDatabase(0);
  4. // 构造RedissonClient
  5. RedissonClient redissonClient = Redisson.create(config);
  6. // 设置锁定资源名称
  7. RLock disLock = redissonClient.getLock("DISLOCK");
  8. boolean isLock;
  9. try {
  10. //尝试获取分布式锁
  11. isLock = disLock.tryLock(500, 15000, TimeUnit.MILLISECONDS);
  12. if (isLock) {
  13. //TODO if get lock success, do something;
  14. Thread.sleep(15000);
  15. }
  16. } catch (Exception e) {
  17. } finally {
  18. // 无论如何, 最后都要解锁
  19. disLock.unlock();
  20. }
复制代码

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

  1. 172.29.1.180:5379> hgetall DISLOCK
  2. 1) "01a6d806-d282-4715-9bec-f51b9aa98110:1"
  3. 2) "1"
复制代码

哨兵模式

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

  1. Config config = new Config();
  2. config.useSentinelServers().addSentinelAddress(
  3. "redis://172.29.3.245:26378","redis://172.29.3.245:26379", "redis://172.29.3.245:26380")
  4. .setMasterName("mymaster")
  5. .setPassword("a123456").setDatabase(0);
复制代码

集群模式

集群模式构造Config如下:

  1. Config config = new Config();
  2. config.useClusterServers().addNodeAddress(
  3. "redis://172.29.3.245:6375","redis://172.29.3.245:6376", "redis://172.29.3.245:6377",
  4. "redis://172.29.3.245:6378","redis://172.29.3.245:6379", "redis://172.29.3.245:6380")
  5. .setPassword("a123456").setScanInterval(5000);
复制代码

总结

平常 分布式实现非常简单,无论是那种架构,向Redis通过EVAL下令 实验 LUA脚本即可。

Redlock分布式锁

那么Redlock分布式锁怎样 实现呢?以单机模式Redis架构为例,直接看实当代 码:

  1. Config config1 = new Config();
  2. config1.useSingleServer().setAddress("redis://172.29.1.180:5378")
  3. .setPassword("a123456").setDatabase(0);
  4. RedissonClient redissonClient1 = Redisson.create(config1);
  5. Config config2 = new Config();
  6. config2.useSingleServer().setAddress("redis://172.29.1.180:5379")
  7. .setPassword("a123456").setDatabase(0);
  8. RedissonClient redissonClient2 = Redisson.create(config2);
  9. Config config3 = new Config();
  10. config3.useSingleServer().setAddress("redis://172.29.1.180:5380")
  11. .setPassword("a123456").setDatabase(0);
  12. RedissonClient redissonClient3 = Redisson.create(config3);
  13. String resourceName = "REDLOCK";
  14. RLock lock1 = redissonClient1.getLock(resourceName);
  15. RLock lock2 = redissonClient2.getLock(resourceName);
  16. RLock lock3 = redissonClient3.getLock(resourceName);
  17. RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);
  18. boolean isLock;
  19. try {
  20. isLock = redLock.tryLock(500, 30000, TimeUnit.MILLISECONDS);
  21. System.out.println("isLock = "+isLock);
  22. if (isLock) {
  23. //TODO if get lock success, do something;
  24. Thread.sleep(30000);
  25. }
  26. } catch (Exception e) {
  27. } finally {
  28. // 无论如何, 最后都要解锁
  29. System.out.println("");
  30. redLock.unlock();
  31. }
复制代码

最核心的变化就是RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);,由于 我这里是以三个节点为例。

那么假如 是哨兵模式呢?必要 搭建3个,或者5个sentinel模式集群(具体 多少个,取决于你)。
那么假如 是集群模式呢?必要 搭建3个,或者5个cluster模式集群(具体 多少个,取决于你)。

实现原理

既然核心变化是利用 了RedissonRedLock,那么我们看一下它的源码有什么不同。这个类是RedissonMultiLock的子类,以是 调用tryLock方法时,毕竟 上调用了RedissonMultiLock的tryLock方法,精简源码如下:

  1. public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
  2. // 实现要点之允许加锁失败节点限制
  3. int failedLocksLimit = failedLocksLimit();
  4. List<RLock> acquiredLocks = new ArrayList<RLock>(locks.size());
  5. // 实现要点之遍历所有节点通过EVAL命令执行lua加锁
  6. for (ListIterator<RLock> iterator = locks.listIterator(); iterator.hasNext();) {
  7. RLock lock = iterator.next();
  8. boolean lockAcquired;
  9. try {
  10. // 对节点尝试加锁
  11. lockAcquired = lock.tryLock(awaitTime, newLeaseTime, TimeUnit.MILLISECONDS);
  12. } catch (RedisConnectionClosedException|RedisResponseTimeoutException e) {
  13. // 如果抛出这类异常,为了防止加锁成功,但是响应失败,需要解锁
  14. unlockInner(Arrays.asList(lock));
  15. lockAcquired = false;
  16. } catch (Exception e) {
  17. // 抛出异常表示获取锁失败
  18. lockAcquired = false;
  19. }
  20. if (lockAcquired) {
  21. // 成功获取锁集合
  22. acquiredLocks.add(lock);
  23. } else {
  24. // 如果达到了允许加锁失败节点限制,那么break,即此次Redlock加锁失败
  25. if (locks.size() - acquiredLocks.size() == failedLocksLimit()) {
  26. break;
  27. }
  28. }
  29. }
  30. return true;
  31. }
复制代码

很显着 ,这段源码就是上一篇文章《Redlock:Redis分布式锁最牛逼的实现》提到的Redlock算法的完全实现。

以sentinel模式架构为例,如下图所示,有sentinel-1,sentinel-2,sentinel-3总计3个sentinel模式集群,假如 要获取分布式锁,那么必要 向这3个sentinel集群通过EVAL下令 实验 LUA脚本,必要 3/2+1=2,即至少2个sentinel集群相应 成功,才算成功的以Redlock算法获取到分布式锁:

Redisson实现Redis分布式锁的几种方式

题目 合集

Redisson实现Redis分布式锁的几种方式

根据上面实现原理的分析,这位同砚 应该是对Redlock算法实现有一点点误解,假设我们用5个节点实现Redlock算法的分布式锁。那么要么是5个redis单实例,要么是5个sentinel集群,要么是5个cluster集群。而不是一个有5个主节点的cluster集群,然后向每个节点通过EVAL下令 实验 LUA脚本尝试获取分布式锁,如上图所示。

失效时间怎样 设置
这个题目 的场景是,假设设置失效时间10秒,假如 由于某些缘故起因 导致10秒还没实验 完任务 ,这时间 锁主动 失效,导致其他线程也会拿到分布式锁。

这确实是Redis分布式最大的题目 ,不管是平常 分布式锁,还是Redlock算法分布式锁,都没有办理 这个题目 。也有一些文章提出了对失效时间续租,即延伸 失效时间,很显着 这又提拔 了分布式锁的复杂度。别的 就笔者相识 ,没有现成的框架有实现,假如 有哪位知道,可以告诉我,万分感谢。

redis分布式锁的高可用
关于Redis分布式锁的安全性题目 ,在分布式体系 专家Martin Kleppmann和Redis的作者antirez之间已经发生过一场争论。有爱好 的同砚 ,搜刮 "基于Redis的分布式锁到底安全吗"就能得到你想要的答案,必要 注意 的是,有上下两篇(这应该就是传说中的神仙打架吧,哈)。

zookeeper or redis
没有绝对的好坏,只有更得当 本身 的业务。就性能而言,redis很显着 优于zookeeper;就分布式锁实现的健壮性而言,zookeeper很显着 优于redis。怎样 选择,取决于你的业务!

到此这篇关于Redisson实现Redis分布式锁的几种方式的文章就先容 到这了,更多相干 Redisson实现Redis分布式锁内容请搜刮 脚本之家从前 的文章或继续欣赏 下面的相干 文章渴望 大家以后多多支持脚本之家!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

avatar 婚庆中国掌 | 2021-9-21 05:27:23 | 显示全部楼层
鸟大了,什么林子都敢进啊!
回复

使用道具 举报

avatar 无人岛屿颈 | 2021-10-2 09:47:47 | 显示全部楼层
admin楼主,我告诉你一个你不知道的的秘密,有一个牛逼的网站,影视频道的网站所有电影和连续剧都可以免费看的。访问地址:http://tv.mxswl.com
回复

使用道具 举报

avatar 螃蟹357 | 2021-10-4 10:00:32 | 显示全部楼层
上次给admin楼主开的药,你都吃完了?
回复

使用道具 举报

avatar 樱花283 | 2021-10-5 09:44:02 | 显示全部楼层
admin楼主病的不轻啊!
回复

使用道具 举报

avatar 孤客9116 | 2021-10-5 10:29:38 | 显示全部楼层
admin楼主的等级很高啊!
回复

使用道具 举报

avatar 流动532 | 2021-10-5 19:47:24 | 显示全部楼层
论坛的人气不行了!
回复

使用道具 举报

avatar Mionsterv | 2021-10-5 20:31:59 | 显示全部楼层
听admin楼主一席话,省我十本书!
回复

使用道具 举报

avatar 123457839 | 2021-10-6 01:16:10 | 显示全部楼层
admin楼主,你妈妈喊你回家吃饭!
回复

使用道具 举报

avatar 飘渺九月 | 2021-10-6 04:31:03 | 显示全部楼层
关注一下!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则