预备 知识
Pipeline(管道) 本质是有客户端提供的一种操作,Pipline 通过调整指令列表的读写顺序,可以节省IO时间
简单限流
public class RateLiniter {
private Jedis jedis;
public RateLiniter(Jedis jedis) {
this.jedis = jedis;
}
/**
*
*
* @param user 操作的用户,相当于限流对象
* @param action 具体操作
* @param period 时间窗
* @param maxCount 限流次数
* @return
*/
public boolean isAllowed(String user,String action,int period, int maxCount){
//1 数据用 zset 保存,首先生成一个key
String key = user+"-"+action;
//2 获取当前时间
long nowTime = System.currentTimeMillis();
//3 建立管道
Pipeline pipelined = jedis.pipelined();
//开启管道
pipelined.multi();
//4将当前操作先存储下来
pipelined.zadd(key,nowTime,String.valueOf(nowTime));
//5 移除时间窗之外的数据
pipelined.zremrangeByScore(key,0,nowTime-period*1000);
//6 统计剩下的key
Response<Long> zcard = pipelined.zcard(key);
// 7 将当前key 设置一个过期时间,过期时间就是时间窗
pipelined.expire(key,period+1);
//关闭管道
pipelined.exec();
pipelined.close();
//8比较时间窗内操作数
return zcard.get()<= maxCount;
}
public static void main(String[] args){
Redis redis = new Redis();
redis.execute(jedis -> {
RateLiniter rateLiniter = new RateLiniter(jedis);
for (int i = 0; i < 10; i++) {
System.out.println(rateLiniter.isAllowed("494936", "publish", 5, 3));
}
});
}
}