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
RPermitExpirableSemaphore ,可过期性信号量
接口文档:
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中塞值。

Java中参数相似方法的那些坑

最近遇见的一些问题,记录一下
当哨兵发来告警,redis执行缓慢,第一反应是不是有人执行了 keys *,

输入 slowlog get 进行查看,关于slowlog get 的用法 可以参考 http://www.redis.cn/commands/slowlog.html

发现都是一些SET,GET命令,并没那种复杂度高的命令,如SORT这些。

虽然这里没有复杂操作,但是从slowlog 的结果我们继续分析,

除了复杂操作,还有一种情况也会导致Redis卡顿,就是Redis出现了大key。
通过 MEMORY USAGE key 来查看 数据的大小

MEMORY USAGE testkey
integer) 3700347

!一个key竟然有3m多!

利用redis客户端查看数据,发现保存的值都是满屏的\x00\x00!

再去查看代码,发现代码中使用了trim,所以没发现异常。

String value = stringRedisTemplate.opsForValue().get(“testkey”).trim();

接下来就是分析这个大key到底是怎么插进去的

伪代码如下:

stringRedisTemplate.opsForValue().set(“testkey”,“xxx”,60601000);

乍一看没什么问题,set了一个key,设置了过期时间。

点进去源码一看,震惊,最后一个参数根本不是过期时间,而是偏移量 offset。

在这里插入图片描述
stringRedisTemplate.opsForValue().set(“testkey”,“xxx”,60601000);
再来看这个代码,每次给这个key set值,其实都是在扩大这个key。

4个参数的方法才是设置过期时间的
在这里插入图片描述

最后在看下这两个方法,真的很像
在这里插入图片描述
说到这里,想起来redisson中的两个方法:

在这里插入图片描述

你还记得他们的区别吗?

方法2,两个参数的方法,redisson是会帮你自动续期的,因为没有设置leaseTime

不设置leaseTime就会触发redisson的看门狗机制,如果业务没有执行完,会帮你一直续期。 使用场景要根据自己的业务来取舍。
在这里插入图片描述

而方法1,三个参数的方法,只要leaseTime设置了,就会在 leaseTime到期后,锁也一并失效。

一般情况下,我们使用三个参数的方法较为常见。

备注:
在这里插入图片描述

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值