场景
为防止用户在短时间内对服务器发起大量请求,服务器端须判断某一用户(userId)的某一个行为(actionKey)在指定时间段(period)内是否超出最大请求次数(maxCount),如果未超过,返回 true ,继续执行业务逻辑,否则返回 false
原理
以用户lucas的reply请求为例。
lucas向服务器发起一次reply请求,先检查系统中保存的以lucas+reply为key的记录的数量N,如果N大于maxCount,返回 false。如果N小于maxCount,将lucas+reply 作为 zset 的 key,当前时间作为zset的member 和 score 插入到zset中,返回 true。
因为系统只需检查从 (当前时间 - period) 到 当前时间 这段时间内用户行为的请求数量,因此可以将小于(当前时间 - period)的所有用户的所有行为的记录删除,因此可以为每条记录设置过期时间。
代码
以下代码参考 钱文品《Redis深度历险:核心原理和应用实践》应用 6:断尾求生——简单限流 ,但有逻辑上的不同。
package me.lucas.redisinaction.redis;
import redis.clients.jedis.Jedis;
/**
* 用redis zset实现的简单的限流策略
* 限定 userId 的 actionKey 行为在 period 秒内只允许发生 maxCount 次
* Author: lin
* Date: 2019/9/12 9:57
*/
public class MySimpleRateLimiter {
private Jedis jedis;
private MySimpleRateLimiter(Jedis jedis) {
this.jedis = jedi