RRateLimiter的使用Demo
1 | public class RRateLimiterDemo { |
RRateLimiter的基本原理
setRate设置速率
会向Redis中设计速率、时间间隔、和对应的模式。整个为hash结构,
1 | redis.call('hsetnx', KEYS[1], 'rate', ARGV[1]); -- 速率 比如1s产生2个令牌 速率就是2 |
尝试获取一个许可
1 | -- 速率 |
总结一下,redisson用了zset来记录请求的信息,这样可以非常巧妙的通过比较score,也就是请求的时间戳,来判断当前请求距离上一个请求有没有超过一个令牌生产周期。如果超过了,则说明令牌桶中的令牌需要生产,之前用掉了多少个就生产多少个,而之前用掉了多少个令牌的信息也在zset中保存了。
LUA脚本返回后的处理
1 | private void tryAcquireAsync(long permits, RPromise<Boolean> promise, long timeoutInMillis) { |
再次总结一下,Java客户端拿到redis返回的下一个令牌生产完成还需要多少时间,也就是delay字段。如果这个delay为null,则表示成功获得令牌,如果没拿到,则过delay时间后通过异步线程再次发起拿令牌的动作。这里也可以看到,redisson的RateLimiter是非公平的,多个线程同时拿不到令牌的话并不保证先请求的会先拿到令牌。