某些场景下需要考虑信号量机制,比如控制整体的并发量,redisson提供了在分布式环境下的解决方案,即 PermitExpirableSemaphore。

记录一下,主要是是否会重复初始化导致重置可用信号量、如何变更总可用信号量。

使用非常简单,以下是官方的使用示例:

RPermitExpirableSemaphore semaphore = redisson.getPermitExpirableSemaphore("mySemaphore");semaphore.trySetPermits(23);// acquire permit
String id = semaphore.acquire();// or acquire permit with lease time in 10 seconds
String id = semaphore.acquire(10, TimeUnit.SECONDS);// or try to acquire permit
String id = semaphore.tryAcquire();// or try to acquire permit or wait up to 15 seconds
String id = semaphore.tryAcquire(15, TimeUnit.SECONDS);// or try to acquire permit with least time 15 seconds or wait up to 10 seconds
String id = semaphore.tryAcquire(10, 15, TimeUnit.SECONDS);
if (id != null) {try {...} finally {semaphore.release(id);}
}

实际在redis中,存储了两个key数据:

1、初始化时"传入名称",string类型,存储可用信号量

2、 "{传入名称}:timeout",zset类型,存储已申请的信号量id、过期时间。

里面有几个关键方法,解析如下:

一、semaphore.trySetPermits(23)

即设置许可证数量,它的关键实现如下:

    public RFuture<Boolean> trySetPermitsAsync(int permits) {return commandExecutor.evalWriteAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,"local value = redis.call('get', KEYS[1]); " +"if (value == false or value == 0) then "+ "redis.call('set', KEYS[1], ARGV[1]); "+ "redis.call('publish', KEYS[2], ARGV[1]); "+ "return 1;"+ "end;"+ "return 0;",Arrays.<Object>asList(getRawName(), getChannelName()), permits);}

即key存在,且不为数字0时,注意这里的数字 0,这个保证了即使许可证被用完了,也不会被重置。

二、semaphore.tryAcquire(15, TimeUnit.SECONDS)

申请一个许可证,15秒超时,这里源码比较长,就不贴了,基本思路是:

1、删除timeout中已过期的信号量数据

2、有过期的,增加可用信号量数量

3、如果可用信号量大于等于需要申请的信号量,可用信号量-1,timeout中增加申请的信号量数据

三、semaphore.release(id)

删除timeout中该信号量数据,增加可申请信号量

四、semaphore.addPermits(permits)

调整总信号量数,正数增加,负数减少

    public RFuture<Void> addPermitsAsync(int permits) {return commandExecutor.evalWriteAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_VOID,"local value = redis.call('get', KEYS[1]); " +"if (value == false) then "+ "value = 0;"+ "end;"+ "redis.call('set', KEYS[1], tonumber(value) + tonumber(ARGV[1])); "+ "if tonumber(ARGV[1]) > 0 then "+ "redis.call('publish', KEYS[2], ARGV[1]); "+ "end;",Arrays.<Object>asList(getRawName(), getChannelName()), permits);}

如果已经初始化,直接修改剩余信号量数据为:剩余可用信号量+增加/减少的信号量。

四、结论

回答最初的问题:

1、重复调用trySetPermits,不会对已有信号量设置造成影响,因为string类型,一旦初始化,则 value == 0 这个条件永远不可能满足

2、修改信号量时,只能手动执行一次,可以使用addPermits方法或者让运维直接使用 incrby/decrby 指令修改剩余信号量值,增加/减少总信号量

Redisson PermitExpirableSemaphore 剖析相关推荐

  1. 老夫带你深度剖析Redisson实现分布式锁的原理

    Redis实现分布式锁的原理 前面讲了Redis在实际业务场景中的应用,那么下面再来了解一下Redisson功能性场景的应用,也就是大家经常使用的分布式锁的实现场景. 引入redisson依赖 < ...

  2. redis ,redisson 分布式锁深入剖析

    目录 为什么要用分布式锁? 分布式锁所遵循的原则? redis 分布式锁 redis 原始分布式锁实现 加锁 释放锁 redis 分布式锁存在的问题 redisson  实现分布式锁 redisson ...

  3. 深度剖析:Redis分布式锁到底安全吗?看完这篇文章彻底懂了!

    ‍‍‍‍‍‍‍‍‍‍‍‍阅读本文大约需要 20 分钟. 大家好,我是 Kaito. 这篇文章我想和你聊一聊,关于 Redis 分布式锁的「安全性」问题. Redis 分布式锁的话题,很多文章已经写烂了 ...

  4. java分布式锁终极解决方案之 redisson

    目前有很多项目还在使用redis的 setNx 充当分布式锁,然而这个锁是有问题的,redisson是java支持redis的redlock的唯一实现,.目前支持集群模式,云托管模式,单Redis节点 ...

  5. Redisson官方文档 - 目录

    Redisson项目介绍 1. 概述 2. 配置方法 2.1. 程序化配置 2.2. 文件方式配置 2.2.1 通过JSON或YAML格式配置 2.2.2 通过Spring XML命名空间配置 2.3 ...

  6. 分布式锁中的王者方案:Redisson

    我们先来看下 Redis 官网对分布式锁的说法: 而 Java 版的 分布式锁的框架就是 Redisson. 本篇实战内容将会基于我的开源项目 PassJava 来整合 Redisson. 我把后端. ...

  7. redisson的锁的类型_你知道吗?大家都在使用Redisson实现分布式锁了!!

    Redisson框架十分强大,基于Redisson框架可以实现几乎你能想到的所有类型的分布式锁.这里,我就列举几个类型的分布式锁,并各自给出一个示例程序来加深大家的理解.有关分布式锁的原理细节,后续专 ...

  8. 深度剖析:Redis 分布式锁到底安全吗?看完这篇文章彻底懂了!

    作者 | Kaito 来源 | 水滴与银弹 阅读本文大约需要 20 分钟. 大家好,我是 Kaito. 这篇文章我想和你聊一聊,关于 Redis 分布式锁的「安全性」问题. Redis 分布式锁的话题 ...

  9. 万字长文剖析Redis分布式锁到底安不安全

    ‍‍‍‍‍‍‍‍‍‍‍‍阅读本文大约需要 20 分钟. 这篇文章我想和你聊一聊,关于 Redis 分布式锁的「安全性」问题. Redis 分布式锁的话题,很多文章已经写烂了,我为什么还要写这篇文章呢? ...

最新文章

  1. java oracle in 10000_java支持ORACLE的in不能超过1000
  2. 无线路由器桥接与覆盖
  3. mysql字符串相加函数concat()
  4. 做微波有源电路的设计仿真 一般都用什么软件 matlab可以吗,MATLAB在有源滤波器仿真设计中的应用...
  5. 2.1.1 Speed Limit
  6. iview weapp icon组件自定义图标 小程序
  7. 跨平台、跨语言应用开发工具,Elements 介绍
  8. 教你一招轻松入门python,不收藏等于错失了一个亿!
  9. Swagger:后端文档生成工具
  10. 小程序 | 微信小程序实现图片是上传、预览功能
  11. 动态添加控件[可重复同一控件]
  12. 第十八章 lamp架构
  13. ZOJ 3502 Contest 状态压缩 概率 DP
  14. 西门子s300编程实例_数控车床加工编程典型实例分析(西门子802S数控系统编程教学)...
  15. php读取服务器csv文件,PHP进行读取CSV文件数据和生成CSV文件
  16. 音乐学院计算机音乐实验中心,中央音乐学院鼎石实验学校
  17. vue 和 react的对比
  18. 展示一下香蕉派路由Android系统
  19. Misc简单题目分享-CTF
  20. linux内核形式化验证,聪明人的笨功夫 -- MesaTEE安全形式化验证实践

热门文章

  1. Linux镜像run起来,六、Docker run 运行镜像
  2. 优普丰敏捷学院Bill和Jacky的敏捷管理者领导力培训课程
  3. Vue - 项目中使用iconfont(阿里图标库)
  4. Python-王者荣耀自动刷金币+爬取英雄信息+图片
  5. wx.createinneraudiocontext微信开发者工具没有声音
  6. 当乐网CEO肖永泉:手机游戏赚钱已经不成问题
  7. SQL教程——循环结构
  8. 什么是DNS,怎么用虚拟机搭建DNS服务器
  9. (20200327已解决)used in key specification without a key length
  10. centos7 top命令详解