Redisson PermitExpirableSemaphore 剖析
某些场景下需要考虑信号量机制,比如控制整体的并发量,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 剖析相关推荐
- 老夫带你深度剖析Redisson实现分布式锁的原理
Redis实现分布式锁的原理 前面讲了Redis在实际业务场景中的应用,那么下面再来了解一下Redisson功能性场景的应用,也就是大家经常使用的分布式锁的实现场景. 引入redisson依赖 < ...
- redis ,redisson 分布式锁深入剖析
目录 为什么要用分布式锁? 分布式锁所遵循的原则? redis 分布式锁 redis 原始分布式锁实现 加锁 释放锁 redis 分布式锁存在的问题 redisson 实现分布式锁 redisson ...
- 深度剖析:Redis分布式锁到底安全吗?看完这篇文章彻底懂了!
阅读本文大约需要 20 分钟. 大家好,我是 Kaito. 这篇文章我想和你聊一聊,关于 Redis 分布式锁的「安全性」问题. Redis 分布式锁的话题,很多文章已经写烂了 ...
- java分布式锁终极解决方案之 redisson
目前有很多项目还在使用redis的 setNx 充当分布式锁,然而这个锁是有问题的,redisson是java支持redis的redlock的唯一实现,.目前支持集群模式,云托管模式,单Redis节点 ...
- Redisson官方文档 - 目录
Redisson项目介绍 1. 概述 2. 配置方法 2.1. 程序化配置 2.2. 文件方式配置 2.2.1 通过JSON或YAML格式配置 2.2.2 通过Spring XML命名空间配置 2.3 ...
- 分布式锁中的王者方案:Redisson
我们先来看下 Redis 官网对分布式锁的说法: 而 Java 版的 分布式锁的框架就是 Redisson. 本篇实战内容将会基于我的开源项目 PassJava 来整合 Redisson. 我把后端. ...
- redisson的锁的类型_你知道吗?大家都在使用Redisson实现分布式锁了!!
Redisson框架十分强大,基于Redisson框架可以实现几乎你能想到的所有类型的分布式锁.这里,我就列举几个类型的分布式锁,并各自给出一个示例程序来加深大家的理解.有关分布式锁的原理细节,后续专 ...
- 深度剖析:Redis 分布式锁到底安全吗?看完这篇文章彻底懂了!
作者 | Kaito 来源 | 水滴与银弹 阅读本文大约需要 20 分钟. 大家好,我是 Kaito. 这篇文章我想和你聊一聊,关于 Redis 分布式锁的「安全性」问题. Redis 分布式锁的话题 ...
- 万字长文剖析Redis分布式锁到底安不安全
阅读本文大约需要 20 分钟. 这篇文章我想和你聊一聊,关于 Redis 分布式锁的「安全性」问题. Redis 分布式锁的话题,很多文章已经写烂了,我为什么还要写这篇文章呢? ...
最新文章
- java oracle in 10000_java支持ORACLE的in不能超过1000
- 无线路由器桥接与覆盖
- mysql字符串相加函数concat()
- 做微波有源电路的设计仿真 一般都用什么软件 matlab可以吗,MATLAB在有源滤波器仿真设计中的应用...
- 2.1.1 Speed Limit
- iview weapp icon组件自定义图标 小程序
- 跨平台、跨语言应用开发工具,Elements 介绍
- 教你一招轻松入门python,不收藏等于错失了一个亿!
- Swagger:后端文档生成工具
- 小程序 | 微信小程序实现图片是上传、预览功能
- 动态添加控件[可重复同一控件]
- 第十八章 lamp架构
- ZOJ 3502	 Contest 状态压缩 概率 DP
- 西门子s300编程实例_数控车床加工编程典型实例分析(西门子802S数控系统编程教学)...
- php读取服务器csv文件,PHP进行读取CSV文件数据和生成CSV文件
- 音乐学院计算机音乐实验中心,中央音乐学院鼎石实验学校
- vue 和 react的对比
- 展示一下香蕉派路由Android系统
- Misc简单题目分享-CTF
- linux内核形式化验证,聪明人的笨功夫 -- MesaTEE安全形式化验证实践
热门文章
- Linux镜像run起来,六、Docker run 运行镜像
- 优普丰敏捷学院Bill和Jacky的敏捷管理者领导力培训课程
- Vue - 项目中使用iconfont(阿里图标库)
- Python-王者荣耀自动刷金币+爬取英雄信息+图片
- wx.createinneraudiocontext微信开发者工具没有声音
- 当乐网CEO肖永泉:手机游戏赚钱已经不成问题
- SQL教程——循环结构
- 什么是DNS,怎么用虚拟机搭建DNS服务器
- (20200327已解决)used in key specification without a key length
- centos7 top命令详解