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也是我的号。

posted @ 2018-09-05 21:11  永远的七号  阅读(3001)  评论(0编辑  收藏  举报