Redission 中 RPermitExpirableSemaphore 用法
RPermitExpirableSemaphore是什么
首先,RPermitExpirableSemaphore 是出自于Redisson,Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid),Redisson也是redis官方推荐的,比较常用的是它的分布式锁。
Redisson中文文档:
[https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95)
RPermitExpirableSemaphore ,可过期性信号量
接口文档:
[https://www.javadoc.io/doc/org.redisson/redisson/latest/index.html](https://www.javadoc.io/doc/org.redisson/redisson/latest/index.html)
用法
举个栗子
创建RedissonClient 单机版
@Bean public RedissonClient redissonClient() { Config config = new Config(); // 单机模式 config.useSingleServer() .setAddress("redis://127.0.0.1:6379") ; return Redisson.create(config); }
一次完整的获得许可,释放许可
public void test() throws Exception { //通过redissonClient创造一个key为xxx的信号量 RPermitExpirableSemaphore semaphore = redissonClient.getPermitExpirableSemaphore("xxx"); //给信号量设置数量为5,用在限流中就是只允许5次请求 while (!semaphore.trySetPermits(5)) ; //tryAcquire 的第一个参数是waittime,尝试获得许可证的最大等待时间,超过这个时间则返回null //第二个参数是许可证的过期时间,也是精华所在,即使发生宕机,jvm崩溃等情况,也不用担心,信号量过期会自动释放 //成功之后会获得一个许可证ID,是在获取期间每次生成的128位唯一随机标识符 String permitId = semaphore.tryAcquire(1, 5, TimeUnit.SECONDS); System.out.println(permitId); //释放许可证还需要之前获得permitId semaphore.release(permitId); }
semaphore.trySetPermits() 中 lua脚本分析
@Override public RFuture<Boolean> trySetPermitsAsync(int permits) { return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, "local value = redis.call('get', KEYS[1]); " + //value==0或者false,都是代表没有这个信号量,进入创建信号量的逻辑 "if (value == false or value == 0) then " //所谓创建,其实就是redis的set操作, ARGV[1]即为要设置的许可数 + "redis.call('set', KEYS[1], ARGV[1]); " + "redis.call('publish', KEYS[2], ARGV[1]); " + "return 1;" + "end;" + "return 0;", Arrays.<Object>asList(getName(), getChannelName()), permits); }
异常记录
1.`Caused by: org.redisson.client.RedisException: ERR This instance has cluster support disabled. channel: [id: 0x0fd46049, L:/127.0.0.1:62555 - R:/127.0.0.1:6379] command: CommandData [promise=org.redisson.misc.RedissonPromise@74bd3426[Not completed], command=(CLUSTER NODES), params=[], codec=null]
`
是由于设置了集群
```
Config config = new Config();
// set集群版报错
config.useClusterServers()
.addNodeAddress("redis://127.0.0.1:6379")
```
应该为
```
config.useSingleServer()
.setAddress("redis://127.0.0.1:6379")
```
2.trySetPermits 一直返回的false,可以查看下是否redis中有了相同的key,trySetPermits 其实就是往redis中塞值。
另外,浅蓝浅蓝777也是我的号。