Redis 限流的 3 種方式,還有誰不會!
1第一種:基于Redis的setnx的操作
2第二種:基于Redis的數(shù)據(jù)結(jié)構(gòu)zset
public Response limitFlow(){
Long currentTime = new Date().getTime();
System.out.println(currentTime);
if(redisTemplate.hasKey("limit")) {
Integer count = redisTemplate.opsForZSet().rangeByScore("limit", currentTime - intervalTime, currentTime).size(); // intervalTime是限流的時間
System.out.println(count);
if (count != null && count > 5) {
return Response.ok("每分鐘最多只能訪問5次");
}
}
redisTemplate.opsForZSet().add("limit",UUID.randomUUID().toString(),currentTime);
return Response.ok("訪問成功");
}
通過上述代碼可以做到滑動窗口的效果,并且能保證每N秒內(nèi)至多M個請求,缺點就是zset的數(shù)據(jù)結(jié)構(gòu)會越來越大。實現(xiàn)方式相對也是比較簡單的。
3第三種:基于Redis的令牌桶算法
// 輸出令牌
public Response limitFlow2(Long id){
Object result = redisTemplate.opsForList().leftPop("limit_list");
if(result == null){
return Response.ok("當(dāng)前令牌桶中無令牌");
}
return Response.ok(articleDescription2);
}
再依靠Java的定時任務(wù),定時往List中rightPush令牌,當(dāng)然令牌也需要唯一性,所以我這里還是用UUID進(jìn)行了生成
// 10S的速率往令牌桶中添加UUID,只為保證唯一性
@Scheduled(fixedDelay = 10_000,initialDelay = 0)
public void setIntervalTimeTask(){
redisTemplate.opsForList().rightPush("limit_list",UUID.randomUUID().toString());
}
綜上,代碼實現(xiàn)起始都不是很難,針對這些限流方式我們可以在AOP或者filter中加入以上代碼,用來做到接口的限流,最終保護(hù)你的網(wǎng)站。
有問題歡迎留言探討。
評論
圖片
表情
