redisson+spring aop实现限流

redisson的限流原理(后面还有新版本方案)

RRateLimiter limiter = redisson.getRateLimiter("myLimiter");
// one permit per 2 seconds
limiter.trySetRate(RateType.OVERALL, 1, 2, RateIntervalUnit.SECONDS);
limiter.acquire(1);

下面是 RedissonRateLimiter.java#RFuture<T> tryAcquireAsync(RedisCommand<T> command, Long value)

return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, command,
        "local rate = redis.call('hget', KEYS[1], 'rate');"
      + "local interval = redis.call('hget', KEYS[1], 'interval');"
      + "local type = redis.call('hget', KEYS[1], 'type');"
      + "assert(rate ~= false and interval ~= false and type ~= false, 'RateLimiter is not initialized')"
      
      + "local valueName = KEYS[2];"
      + "if type == '1' then "
          + "valueName = KEYS[3];"
      + "end;"
      
      + "local currentValue = redis.call('get', valueName); "
      + "if currentValue ~= false then "
             + "if tonumber(currentValue) < tonumber(ARGV[1]) then "
                 + "return redis.call('pttl', valueName); "
             + "else "
                 + "redis.call('decrby', valueName, ARGV[1]); "
                 + "return nil; "
             + "end; "
      + "else "
             + "redis.call('set', valueName, rate, 'px', interval); "
             + "redis.call('decrby', valueName, ARGV[1]); "
             + "return nil; "
      + "end;",
        Arrays.<Object>asList(getName(), getValueName(), getClientValueName()),
        value, commandExecutor.getConnectionManager().getId().toString());
evalWriteAsync(String key, Codec codec, RedisCommand<T> evalCommandType, String script, List<Object> keys, Object... params);

解释: 上面是限流器代码,下面是分析
key 应该就是限流器名称
Codec 报文解码
command 根据是阻塞获取,还是非阻塞获取,还是有超时时间获取,传递的command不一样,应该是转换结果用
script lua脚本
keys
[1] 限流器名称 redis中是hashmap
[2] value 当全局控制数目用keys[2]
[3] 客户端id 当分客户端限流用 keys[3] 注意lua数组下标从1开始
脚本前3句获取限流器属性,rate interval type,也就是trySetRate设置的属性,如果全局限流,用keys[2] 否则用keys[3]
获取当前值,注意,只有一个值,控制次数 转为数字,看许可是否够,如果不够,pttl命令(当 key 不存在时,返回 -2 。 当 key 存在但没有设置剩余生存时间时,返回 -1 。 否则,以毫秒为单位,返回 key 的剩余生存时间)
许可够用则扣减
如果值不存在 set px 设置多少毫秒后过期,在trySetRate中把时间统一转为毫秒,所以这里可以直接用,见下方。
初始化之后直接扣减,然后返回nil

@Override
public RFuture<Boolean> trySetRateAsync(RateType type, long rate, long rateInterval, RateIntervalUnit unit) {
    return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值