Redis 赶走限流的三种方法
发布日期:2022-06-18 17:09 点击次数:100面临越来越多的高并发场景,限流自满的尤为遑急。
虽然,限流有许多种赶走的方法,Redis具有很宏大的功能,我用Redis实行了三种的赶走方法,不错较为简便的赶走其方法。Redis不单是是不错做限流,还不错做数据统计,隔壁的人等功能,这些可能会后续写到。
第一种:基于Redis的setnx的操作咱们在使用Redis的散布式锁的时候,人人都袒露是依靠了setnx的领导,在CAS(Compare and swap)的操作的时候,同期给指定的key成就了落伍实行(expire),咱们在限流的主要目的等于为了在单元技艺内,有且仅有N数目的恳求大致走访我的代码要领。是以依靠setnx不错很减弱的做到这方面的功能。
比如咱们需要在10秒内铁心20个恳求,那么咱们在setnx的时候不错成就落伍技艺10,当恳求的setnx数目达到20时候即达到了限流遵循。代码比拟简便就不做展示了。
具体的setnx用法不错参照我另一篇博客 RedisTemplate下Redis散布式锁激发的系列问题
虽然这种做法的弱点是好多的,比如当统计1-10秒的时候,无法统计2-11秒之内,如若需要统计N秒内的M个恳求,那么咱们的Redis中需要保持N个key等等问题
第二种:基于Redis的数据结构zset其实限流触及的最主要的等于滑动窗口, 小12萝8禁在线喷水观看上头也提到1-10怎样变成2-11。其实也等于肇始值和结尾值都各+1即可。
而咱们如若用Redis的list数据结构不错胜券在握的赶走该功能
咱们不错将恳求打酿成一个zset数组,当每一次恳求进来的时候,value保持独一,不错用UUID生成,而score不错用现时技艺戳暗示,因为score咱们不错用来臆测现时技艺戳之内有几许的恳求数目。而zset数据结构也提供了range活动让咱们不错很节略的获得到2个技艺戳内有几许恳求
代码如下
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秒内至多M个恳求,污点等于zset的数据结构会越来越大。赶走方法相对亦然比拟简便的。
第三种:基于Redis的令牌桶算法提到限流就不得不提到令牌桶算法了。
令牌桶算法说起到输入速度和输出速度,当输出速度大于输入速度,那么等于超出流量礼貌了。
也等于说咱们每走访一次恳求的时候,不错从Redis中获得一个令牌,如若拿到令牌了,那就诠释没超出礼貌,而如若拿不到,则赶走相悖。
依靠上述的思惟,咱们不错鸠合Redis的List数据结构很节略的做到这么的代码,只是简便赶走
依靠List的leftPop来获得令牌
// 输出令牌 public Response limitFlow2(Long id){ Object result = redisTemplate.opsForList().leftPop("limit_list"); if(result == null){ return Response.ok("现时令牌桶中无令牌"); } return Response.ok(articleDescription2); }
再依靠Java的定时任务,定时往List中rightPush令牌,虽然令牌也需要独一性,是以我这里依然用UUID进行了生成
// 10S的速度往令牌桶中添加UUID,只为保证独一性 @Scheduled(fixedDelay = 10_000,initialDelay = 0) public void setIntervalTimeTask(){ redisTemplate.opsForList().rightPush("limit_list",UUID.randomUUID().toString()); }
综上,代码赶走肇始都不是很难,针对这些限流方法咱们不错在AOP或者filter中加入以上代码,用来做到接口的限流,最终保护你的网站。
Redis其实还有好多其他的用处,他的作用不单是是缓存,散布式锁的作用。他的数据结构也不单是是只须String,Hash,List,Set,Zset。有趣味趣味的不错后续了解下他的GeoHash算法;BitMap,HLL以及布隆过滤器数据(Redis4.0之后加入,不错用Docker平直装配redislabs/rebloom)结构。