限流算法(漏桶算法、令牌桶算法)对比
限流算法(漏桶算法、令牌桶算法)
漏桶算法:
有個桶,比如最大能進2個單位的水(請求),桶底有個洞,每個單位的水都會在桶里待3秒后漏下去。
那么這個桶就可以同時處理2個單位的水。
如果進水太多,同一時間進水多出2個單位的水就溢出來了,也就是拒絕請求或阻塞。
令牌桶算法:
有個桶,每個固定時間會向桶里放令牌,放滿就不放了,而每次請求都會從桶里去拿令牌,拿到才能正常請求。
如果拿的速度大于放的速度,那么就會出現拿不到令牌的情況,請求就會被拒絕或阻塞。
基于漏桶算法的典型實現:java.util.concurrent.Semaphore
基于令牌桶算法是典型實現:com.google.common.util.concurrent.RateLimiter
1、Semaphore(漏桶算法)
Semaphore更傾向于限制并發量,比如系統只支持2個并發,那么就設置:
Semaphore semaphore = new Semaphore(2);
每次請求前,執行semaphore.acquire();相當于將水放在水桶里,最多放2個
請求結束前,執行semaphore.release();相當于把水漏掉
那么效果就是系統每秒只能支持兩個請求,只有等這某個請求執行完,并且釋放掉,才能接收新的請求
2、RateLimiter(令牌桶算法)
RateLimiter更傾向于限制訪問速率,比如系統每秒2次請求,那就設置:
RateLimiter limiter = RateLimiter.create(2.0);
每次請求前,執行limiter.acquire();相當于從桶里取令牌
那效果就是每秒只能有兩個請求取到令牌,其他請求只能阻塞住,等待下一秒
剛開始看這兩種限流算法,有些人會混淆,感覺不到太大的差別,那就試試跑跑下面的例子,感受一下:
public static void main(String[] args) {RateLimiter limiter = RateLimiter.create(2.0); // 這里的2表示每秒允許處理的量為2個for (int i = 1; i <= 10; i++) {limiter.acquire();// 拿令牌,拿不到就阻塞log.info("執行。。。" + i);}} public static void main(String[] args) {Semaphore semaphore = new Semaphore(2);//這里的2表示并發數是2for(int i=0;i<10;i++) {new Thread(()->{try {semaphore.acquire();//入桶,放不下就阻塞log.info(Thread.currentThread().getName()+"執行");Thread.sleep(3000);//睡3秒} catch (InterruptedException e) {e.printStackTrace();}finally {semaphore.release();//釋放}},"線程"+i).start();}}注意比對結果,看for循環里每個執行的速度,你會發現:
使用Semaphore限流的,設置的并發數是2個,那么就是一下子兩個一起執行,完了3秒后都執行完,釋放掉,后兩個再一起執行。重點是一批一批的。
使用RateLimiter限流的,每個執行都是勻速的,設置的每秒2個請求,那就基本上是0.5秒一個,勻速執行。重點是勻速。
具體執行結果可以看下圖:
這個是RateLimiter,可以看到是勻速的執行,0.5秒一個。
這個是Semaphore,是兩個兩個的執行,每3秒2個。
注意
這兩種都是單機版的,分布式環境可以使用redis等分布式唯一存儲來記錄這些值,原理都基本差不多
總結
以上是生活随笔為你收集整理的限流算法(漏桶算法、令牌桶算法)对比的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS中的XML解析
- 下一篇: java8新特性(6)— 日期与时间