久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

Redis實現限流器的方法有哪些

140次閱讀
沒有評論

共計 3786 個字符,預計需要花費 10 分鐘才能閱讀完成。

這篇文章主要介紹了 Redis 實現限流器的方法有哪些的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇 Redis 實現限流器的方法有哪些文章都會有所收獲,下面我們一起來看看吧。

方法一:基于 Redis 的 setnx 的操作

我們在使用 Redis 的分布式鎖的時候,大家都知道是依靠了 setnx 的指令,在 CAS(Compare and swap)的操作的時候,同時給指定的 key 設置了過期實踐(expire),我們在限流的主要目的就是為了在單位時間內,有且僅有 N 數量的請求能夠訪問我的代碼程序。所以依靠 setnx 可以很輕松的做到這方面的功能。

比如我們需要在 10 秒內限定 20 個請求,那么我們在 setnx 的時候可以設置過期時間 10,當請求的 setnx 數量達到 20 時候即達到了限流效果。代碼比較簡單就不做展示了。

當然這種做法的弊端是很多的,比如當統計 1 -10 秒的時候,無法統計 2 -11 秒之內,如果需要統計 N 秒內的 M 個請求,那么我們的 Redis 中需要保持 N 個 key 等等問題。

在具體實現的時候,可以考慮使用攔截器 HandlerInterceptor:

public class RequestCountInterceptor implements HandlerInterceptor {
 private LimitPolicy limitPolicy;
 public RequestCountInterceptor(LimitPolicy limitPolicy) {
 this.limitPolicy = limitPolicy;
 }
 @Override
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (!limitPolicy.canDo()) {
 return false;
 }
 return true;
 }
}

同時添加一個配置 LimitConfiguration:

@Configuration
public class LimitConfiguration implements WebMvcConfigurer {
 @Override
 public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new RequestCountInterceptor(new RedisLimit1())).addPathPatterns( /my/increase 
 }
}

這樣每次在 /my/increase 請求到達 Controller 之前按策略 RedisLimit1 進行限流,原先 Controller 里面的代碼就不用修改了:

@RestController
@RequestMapping(my)
public class MyController {
 int i = 0;
 @RequestMapping(/increase)
 public int increase() {
 return i++;
 }
}

具體的限流邏輯代碼是在 RedisLimit1 類中:

/**
*  方法一:基于 Redis 的 setnx 的操作
public class RedisLimit1 extends LimitPolicy {
 static { setNxExpire();
 }
 private static boolean setNxExpire() { SetParams setParams = new SetParams();
 setParams.nx();
 setParams.px(TIME);
 String result = jedis.set(KEY, COUNT +  , setParams);

 // 設置失敗,說明已經存在,直接減 1,并且返回  return jedis.decrBy(KEY, 1)   0;  }  } public abstract class LimitPolicy {  public static final int COUNT = 10; //10 request  public static final int TIME= 10*1000 ; // 10s  public static final String SUCCESS =  OK  static Jedis jedis = new Jedis();  abstract boolean canDo();}

這樣實現的一個效果是每秒最多請求 10 次。

方法二:基于 Redis 的數據結構 zset

其實限流涉及的最主要的就是滑動窗口,上面也提到 1 -10 怎么變成 2 -11。其實也就是起始值和末端值都各 + 1 即可。
而我們如果用 Redis 的 list 數據結構可以輕而易舉的實現該功能
我們可以將請求打造成一個 zset 數組,當每一次請求進來的時候,value 保持唯一,可以用 UUID 生成,而 score 可以用當前時間戳表示,因為 score 我們可以用來計算當前時間戳之內有多少的請求數量。而 zset 數據結構也提供了 zrange 方法讓我們可以很輕易的獲取到 2 個時間戳內有多少請求

/**
*  方法二:基于 Redis 的數據結構 zset
public class RedisLimit2 extends LimitPolicy {
 public static final String KEY2 =  LIMIT2 
 @Override
 public boolean canDo() { Long currentTime = new Date().getTime();
 System.out.println(currentTime);
 if (jedis.zcard(KEY2)   0) { //  這里不能用 get 判斷,會報錯:WRONGTYPE Operation against a key holding the wrong kind of value
 Integer count = jedis.zrangeByScore(KEY2, currentTime - TIME, currentTime).size(); //  注意這里使用 zrangeByScore,以時間作為 score。zrange key start stop  命令的 start 和 stop 是序號。 System.out.println(count);
 if (count != null   count   COUNT) {
 return false;
 }
 }
 jedis.zadd(KEY2, Double.valueOf(currentTime), UUID.randomUUID().toString());
 return true;
 }
}

通過上述代碼可以做到滑動窗口的效果,并且能保證每 N 秒內至多 M 個請求,缺點就是 zset 的數據結構會越來越大。實現方式相對也是比較簡單的。

方法三:基于 Redis 的令牌桶算法

提到限流就不得不提到令牌桶算法了。令牌桶算法提及到輸入速率和輸出速率,當輸出速率大于輸入速率,那么就是超出流量限制了。也就是說我們每訪問一次請求的時候,可以從 Redis 中獲取一個令牌,如果拿到令牌了,那就說明沒超出限制,而如果拿不到,則結果相反。
依靠上述的思想,我們可以結合 Redis 的 List 數據結構很輕易的做到這樣的代碼,只是簡單實現 依靠 List 的 leftPop 來獲取令牌。

首先配置一個定時任務,通過 redis 的 list 的 rpush 方法每秒插入一個令牌:

@Configuration //1. 主要用于標記配置類,兼備 Component 的效果。@EnableScheduling // 2. 開啟定時任務
public class SaticScheduleTask {
 //3. 添加定時任務
 @Scheduled(fixedRate = 1000)
 private void configureTasks() { LimitPolicy.jedis.rpush( LIMIT3 , UUID.randomUUID().toString());
 }
}

限流時,通過 list 的 lpop 方法從 redis 中獲取對應的令牌,如果獲取成功表明可以執行請求:

/**
*  方法三:令牌桶
public class RedisLimit3 extends LimitPolicy {
 public static final String KEY3 =  LIMIT3 
 @Override
 public boolean canDo() { Object result = jedis.lpop(KEY3);
 if (result == null) {
 return false;
 }
 return true;
 }
}

關于“Redis 實現限流器的方法有哪些”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“Redis 實現限流器的方法有哪些”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注丸趣 TV 行業資訊頻道。

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-07-13發表,共計3786字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 福泉市| 连平县| 沁源县| 来宾市| 宜阳县| 浦北县| 蓝山县| 平陆县| 尼玛县| 交城县| 萍乡市| 鸡东县| 岫岩| 千阳县| 论坛| 禄丰县| 浦北县| 溆浦县| 遵义市| 深泽县| 泰宁县| 玉龙| 湘潭县| 内黄县| 巧家县| 梅河口市| 浏阳市| 夹江县| 成安县| 祁阳县| 义乌市| 盖州市| 牟定县| 青海省| 湘潭县| 永新县| 巴林左旗| 屏东市| 盐池县| 土默特左旗| 左云县|