日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁 > 科技  > 軟件

面試必備:四種經(jīng)典限流算法講解

來源: 責(zé)編: 時間:2024-02-29 14:39:54 161觀看
導(dǎo)讀前言大家好,我是田螺。最近一位朋友去拼夕夕面試,被問了這么一道題:限流算法有哪些?用代碼實現(xiàn)令牌桶算法。跟星球好友討論了一波,發(fā)現(xiàn)大家都忘記得差不多了.所以田螺哥再整理一波,常見的四種限流算法,以及簡單代碼實

前言

大家好,我是田螺。DEF28資訊網(wǎng)——每日最新資訊28at.com

最近一位朋友去拼夕夕面試,被問了這么一道題:限流算法有哪些?用代碼實現(xiàn)令牌桶算法。跟星球好友討論了一波,發(fā)現(xiàn)大家都忘記得差不多了.所以田螺哥再整理一波,常見的四種限流算法,以及簡單代碼實現(xiàn),相信大家看完,會茅塞頓開的。DEF28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片DEF28資訊網(wǎng)——每日最新資訊28at.com

1. 固定窗口限流算法

1.1 什么是固定窗口限流算法

固定窗口限流算法(Fixed Window Rate Limiting Algorithm)是一種最簡單的限流算法,其原理是在固定時間窗口(單位時間)內(nèi)限制請求的數(shù)量。該算法將時間分成固定的窗口,并在每個窗口內(nèi)限制請求的數(shù)量。具體來說,算法將請求按照時間順序放入時間窗口中,并計算該時間窗口內(nèi)的請求數(shù)量,如果請求數(shù)量超出了限制,則拒絕該請求。DEF28資訊網(wǎng)——每日最新資訊28at.com

假設(shè)單位時間(固定時間窗口)是1秒,限流閥值為3。在單位時間1秒內(nèi),每來一個請求,計數(shù)器就加1,如果計數(shù)器累加的次數(shù)超過限流閥值3,后續(xù)的請求全部拒絕。等到1s結(jié)束后,計數(shù)器清0,重新開始計數(shù)。如下圖:DEF28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片DEF28資訊網(wǎng)——每日最新資訊28at.com

1.2 固定窗口限流的偽代碼

public static Integer counter = 0;  //統(tǒng)計請求數(shù)   public static long lastAcquireTime =  0L;   public static final Long windowUnit = 1000L ; //假設(shè)固定時間窗口是1000ms   public static final Integer threshold = 10; // 窗口閥值是10       /**     * 固定窗口時間算法     * 關(guān)注公眾號:撿田螺的小男孩     * @return     */    public synchronized boolean fixedWindowsTryAcquire() {        long currentTime = System.currentTimeMillis();  //獲取系統(tǒng)當(dāng)前時間        if (currentTime - lastAcquireTime > windowUnit) {  //檢查是否在時間窗口內(nèi)            counter = 0;  // 計數(shù)器清0            lastAcquireTime = currentTime;  //開啟新的時間窗口        }        if (counter < threshold) {  // 小于閥值            counter++;  //計數(shù)統(tǒng)計器加1            return true;        }        return false;    }

1.2 固定窗口算法的優(yōu)缺點

  • 優(yōu)點:固定窗口算法非常簡單,易于實現(xiàn)和理解。
  • 缺點:存在明顯的臨界問題,比如: 假設(shè)限流閥值為5個請求,單位時間窗口是1s,如果我們在單位時間內(nèi)的前0.8-1s和1-1.2s,分別并發(fā)5個請求。雖然都沒有超過閥值,但是如果算0.8-1.2s,則并發(fā)數(shù)高達(dá)10,已經(jīng)超過單位時間1s不超過5閥值的定義啦。

圖片圖片DEF28資訊網(wǎng)——每日最新資訊28at.com

2. 滑動窗口限流算法

2.1 什么是滑動窗口限流算法

滑動窗口限流算法是一種常用的限流算法,用于控制系統(tǒng)對外提供服務(wù)的速率,防止系統(tǒng)被過多的請求壓垮。它將單位時間周期分為n個小周期,分別記錄每個小周期內(nèi)接口的訪問次數(shù),并且根據(jù)時間滑動刪除過期的小周期。它可以解決固定窗口臨界值的問題。DEF28資訊網(wǎng)——每日最新資訊28at.com

用一張圖解釋滑動窗口算法,如下:DEF28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片DEF28資訊網(wǎng)——每日最新資訊28at.com

假設(shè)單位時間還是1s,滑動窗口算法把它劃分為5個小周期,也就是滑動窗口(單位時間)被劃分為5個小格子。每格表示0.2s。每過0.2s,時間窗口就會往右滑動一格。然后呢,每個小周期,都有自己獨立的計數(shù)器,如果請求是0.83s到達(dá)的,0.8~1.0s對應(yīng)的計數(shù)器就會加1。DEF28資訊網(wǎng)——每日最新資訊28at.com

我們來看下,滑動窗口,去解決固定窗口限流算法的臨界問題,思想是怎樣DEF28資訊網(wǎng)——每日最新資訊28at.com

假設(shè)我們1s內(nèi)的限流閥值還是5個請求,0.8~1.0s內(nèi)(比如0.9s的時候)來了5個請求,落在黃色格子里。時間過了1.0s這個點之后,又來5個請求,落在紫色格子里。如果是固定窗口算法,是不會被限流的,但是滑動窗口的話,每過一個小周期,它會右移一個小格。過了1.0s這個點后,會右移一小格,當(dāng)前的單位時間段是0.2~1.2s,這個區(qū)域的請求已經(jīng)超過限定的5了,已觸發(fā)限流啦,實際上,紫色格子的請求都被拒絕啦。DEF28資訊網(wǎng)——每日最新資訊28at.com

當(dāng)滑動窗口的格子周期劃分的越多,那么滑動窗口的滾動就越平滑,限流的統(tǒng)計就會越精確。DEF28資訊網(wǎng)——每日最新資訊28at.com

2.2 滑動窗口限流算法的偽代碼實現(xiàn)

/**     * 單位時間劃分的小周期(單位時間是1分鐘,10s一個小格子窗口,一共6個格子)     */    private int SUB_CYCLE = 10;    /**     * 每分鐘限流請求數(shù)     */    private int thresholdPerMin = 100;    /**     * 計數(shù)器, k-為當(dāng)前窗口的開始時間值秒,value為當(dāng)前窗口的計數(shù)     */    private final TreeMap<Long, Integer> counters = new TreeMap<>();   /**     * 滑動窗口時間算法實現(xiàn)     */     public synchronized boolean slidingWindowsTryAcquire() {        long currentWindowTime = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) / SUB_CYCLE * SUB_CYCLE; //獲取當(dāng)前時間在哪個小周期窗口        int currentWindowNum = countCurrentWindow(currentWindowTime); //當(dāng)前窗口總請求數(shù)        //超過閥值限流        if (currentWindowNum >= thresholdPerMin) {            return false;        }        //計數(shù)器+1        counters.get(currentWindowTime)++;        return true;    }   /**    * 統(tǒng)計當(dāng)前窗口的請求數(shù)    */    private int countCurrentWindow(long currentWindowTime) {        //計算窗口開始位置        long startTime = currentWindowTime - SUB_CYCLE* (60s/SUB_CYCLE-1);        int count = 0;        //遍歷存儲的計數(shù)器        Iterator<Map.Entry<Long, Integer>> iterator = counters.entrySet().iterator();        while (iterator.hasNext()) {            Map.Entry<Long, Integer> entry = iterator.next();            // 刪除無效過期的子窗口計數(shù)器            if (entry.getKey() < startTime) {                iterator.remove();            } else {                //累加當(dāng)前窗口的所有計數(shù)器之和                count =count + entry.getValue();            }        }        return count;    }

2.3 滑動窗口限流算法的優(yōu)缺點

優(yōu)點:DEF28資訊網(wǎng)——每日最新資訊28at.com

  • 簡單易懂
  • 精度高(通過調(diào)整時間窗口的大小來實現(xiàn)不同的限流效果)
  • 可擴(kuò)展性強(qiáng)(可以非常容易地與其他限流算法結(jié)合使用)

缺點:DEF28資訊網(wǎng)——每日最新資訊28at.com

  • 突發(fā)流量無法處理(無法應(yīng)對短時間內(nèi)的大量請求,但是一旦到達(dá)限流后,請求都會直接暴力被拒絕。醬紫我們會損失一部分請求,這其實對于產(chǎn)品來說,并不太友好),需要合理調(diào)整時間窗口大小。

3. 漏桶限流算法

3.1 什么是漏桶限流算法

漏桶限流算法(Leaky Bucket Algorithm)是一種流量控制算法,用于控制流入網(wǎng)絡(luò)的數(shù)據(jù)速率,以防止網(wǎng)絡(luò)擁塞。它的思想是將數(shù)據(jù)包看作是水滴,漏桶看作是一個固定容量的水桶,數(shù)據(jù)包像水滴一樣從桶的頂部流入桶中,并通過桶底的一個小孔以一定的速度流出,從而限制了數(shù)據(jù)包的流量。DEF28資訊網(wǎng)——每日最新資訊28at.com

漏桶限流算法的基本工作原理是:對于每個到來的數(shù)據(jù)包,都將其加入到漏桶中,并檢查漏桶中當(dāng)前的水量是否超過了漏桶的容量。如果超過了容量,就將多余的數(shù)據(jù)包丟棄。如果漏桶中還有水,就以一定的速率從桶底輸出數(shù)據(jù)包,保證輸出的速率不超過預(yù)設(shè)的速率,從而達(dá)到限流的目的。DEF28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片DEF28資訊網(wǎng)——每日最新資訊28at.com

  • 流入的水滴,可以看作是訪問系統(tǒng)的請求,這個流入速率是不確定的。
  • 桶的容量一般表示系統(tǒng)所能處理的請求數(shù)。
  • 如果桶的容量滿了,就達(dá)到限流的閥值,就會丟棄水滴(拒絕請求)
  • 流出的水滴,是恒定過濾的,對應(yīng)服務(wù)按照固定的速率處理請求。

3.2 漏桶限流算法的偽代碼實現(xiàn)

/** * LeakyBucket 類表示一個漏桶, * 包含了桶的容量和漏桶出水速率等參數(shù), * 以及當(dāng)前桶中的水量和上次漏水時間戳等狀態(tài)。 */public class LeakyBucket {    private final long capacity;    // 桶的容量    private final long rate;        // 漏桶出水速率    private long water;             // 當(dāng)前桶中的水量    private long lastLeakTimestamp; // 上次漏水時間戳    public LeakyBucket(long capacity, long rate) {        this.capacity = capacity;        this.rate = rate;        this.water = 0;        this.lastLeakTimestamp = System.currentTimeMillis();    }    /**     * tryConsume() 方法用于嘗試向桶中放入一定量的水,如果桶中還有足夠的空間,則返回 true,否則返回 false。     * @param waterRequested     * @return     */    public synchronized boolean tryConsume(long waterRequested) {        leak();        if (water + waterRequested <= capacity) {            water += waterRequested;            return true;        } else {            return false;        }    }    /**     * 。leak() 方法用于漏水,根據(jù)當(dāng)前時間和上次漏水時間戳計算出應(yīng)該漏出的水量,然后更新桶中的水量和漏水時間戳等狀態(tài)。     */    private void leak() {        long now = System.currentTimeMillis();        long elapsedTime = now - lastLeakTimestamp;        long leakedWater = elapsedTime * rate / 1000;        if (leakedWater > 0) {            water = Math.max(0, water - leakedWater);            lastLeakTimestamp = now;        }    }}
  • 注意:   tryConsume() 和 leak() 方法中,都需要對桶的狀態(tài)進(jìn)行同步,以保證線程安全性。

3.3 漏桶限流算法的優(yōu)缺點

優(yōu)點DEF28資訊網(wǎng)——每日最新資訊28at.com

  • 可以平滑限制請求的處理速度,避免瞬間請求過多導(dǎo)致系統(tǒng)崩潰或者雪崩。
  • 可以控制請求的處理速度,使得系統(tǒng)可以適應(yīng)不同的流量需求,避免過載或者過度閑置。
  • 可以通過調(diào)整桶的大小和漏出速率來滿足不同的限流需求,可以靈活地適應(yīng)不同的場景。

缺點DEF28資訊網(wǎng)——每日最新資訊28at.com

  • 需要對請求進(jìn)行緩存,會增加服務(wù)器的內(nèi)存消耗。
  • 對于流量波動比較大的場景,需要較為靈活的參數(shù)配置才能達(dá)到較好的效果。
  • 但是面對突發(fā)流量的時候,漏桶算法還是循規(guī)蹈矩地處理請求,這不是我們想看到的啦。流量變突發(fā)時,我們肯定希望系統(tǒng)盡量快點處理請求,提升用戶體驗嘛。

4. 令牌桶算法

4.1 什么是令牌桶算法

令牌桶算法是一種常用的限流算法,可以用于限制單位時間內(nèi)請求的數(shù)量。該算法維護(hù)一個固定容量的令牌桶,每秒鐘會向令牌桶中放入一定數(shù)量的令牌。當(dāng)有請求到來時,如果令牌桶中有足夠的令牌,則請求被允許通過并從令牌桶中消耗一個令牌,否則請求被拒絕。DEF28資訊網(wǎng)——每日最新資訊28at.com

4.2 令牌桶算法的偽代碼實現(xiàn)

/** * TokenBucket 類表示一個令牌桶 */public class TokenBucket {    private final int capacity;     // 令牌桶容量    private final int rate;         // 令牌生成速率,單位:令牌/秒    private int tokens;             // 當(dāng)前令牌數(shù)量    private long lastRefillTimestamp;  // 上次令牌生成時間戳    /**     * 構(gòu)造函數(shù)中傳入令牌桶的容量和令牌生成速率。     * @param capacity     * @param rate     */    public TokenBucket(int capacity, int rate) {        this.capacity = capacity;        this.rate = rate;        this.tokens = capacity;        this.lastRefillTimestamp = System.currentTimeMillis();    }    /**     * allowRequest() 方法表示一個請求是否允許通過,該方法使用 synchronized 關(guān)鍵字進(jìn)行同步,以保證線程安全。     * @return     */    public synchronized boolean allowRequest() {        refill();        if (tokens > 0) {            tokens--;            return true;        } else {            return false;        }    }    /**     * refill() 方法用于生成令牌,其中計算令牌數(shù)量的邏輯是按照令牌生成速率每秒鐘生成一定數(shù)量的令牌,     * tokens 變量表示當(dāng)前令牌數(shù)量,     * lastRefillTimestamp 變量表示上次令牌生成的時間戳。     */    private void refill() {        long now = System.currentTimeMillis();        if (now > lastRefillTimestamp) {            int generatedTokens = (int) ((now - lastRefillTimestamp) / 1000 * rate);            tokens = Math.min(tokens + generatedTokens, capacity);            lastRefillTimestamp = now;        }    }}

4.3 令牌桶算法的優(yōu)缺點

優(yōu)點:DEF28資訊網(wǎng)——每日最新資訊28at.com

  • 穩(wěn)定性高:令牌桶算法可以控制請求的處理速度,可以使系統(tǒng)的負(fù)載變得穩(wěn)定。
  • 精度高:令牌桶算法可以根據(jù)實際情況動態(tài)調(diào)整生成令牌的速率,可以實現(xiàn)較高精度的限流。
  • 彈性好:令牌桶算法可以處理突發(fā)流量,可以在短時間內(nèi)提供更多的處理能力,以處理突發(fā)流量。

Guava的RateLimiter限流組件,就是基于令牌桶算法實現(xiàn)的。DEF28資訊網(wǎng)——每日最新資訊28at.com

缺點:DEF28資訊網(wǎng)——每日最新資訊28at.com

  • 實現(xiàn)復(fù)雜:相對于固定窗口算法等其他限流算法,令牌桶算法的實現(xiàn)較為復(fù)雜。對短時請求難以處理:在短時間內(nèi)有大量請求到來時,可能會導(dǎo)致令牌桶中的令牌被快速消耗完,從而限流。這種情況下,可以考慮使用漏桶算法。
  • 時間精度要求高:令牌桶算法需要在固定的時間間隔內(nèi)生成令牌,因此要求時間精度較高,如果系統(tǒng)時間不準(zhǔn)確,可能會導(dǎo)致限流效果不理想。

總體來說,令牌桶算法具有較高的穩(wěn)定性和精度,但實現(xiàn)相對復(fù)雜,適用于對穩(wěn)定性和精度要求較高的場景。DEF28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-75311-0.html面試必備:四種經(jīng)典限流算法講解

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: Vue2問題:分享一個通用多文件類型預(yù)覽庫

下一篇: 淺談鏈路聚合,你學(xué)會了嗎?

標(biāo)簽:
  • 熱門焦點
  • 線程通訊的三種方法!通俗易懂

    線程通信是指多個線程之間通過某種機(jī)制進(jìn)行協(xié)調(diào)和交互,例如,線程等待和通知機(jī)制就是線程通訊的主要手段之一。 在 Java 中,線程等待和通知的實現(xiàn)手段有以下幾種方式:Object 類下
  • Rust中的高吞吐量流處理

    作者 | Noz編譯 | 王瑞平本篇文章主要介紹了Rust中流處理的概念、方法和優(yōu)化。作者不僅介紹了流處理的基本概念以及Rust中常用的流處理庫,還使用這些庫實現(xiàn)了一個流處理程序
  • 三言兩語說透柯里化和反柯里化

    JavaScript中的柯里化(Currying)和反柯里化(Uncurrying)是兩種很有用的技術(shù),可以幫助我們寫出更加優(yōu)雅、泛用的函數(shù)。本文將首先介紹柯里化和反柯里化的概念、實現(xiàn)原理和應(yīng)用
  • 共享單車的故事講到哪了?

    來源丨海克財經(jīng)與共享充電寶相差不多,共享單車已很久沒有被國內(nèi)熱點新聞關(guān)照到了。除了一再漲價和用戶直呼用不起了。近日多家媒體再發(fā)報道稱,成都、天津、鄭州等地多個共享單
  • 一條抖音4億人圍觀 ! 這家MCN比無憂傳媒還野

    作者:Hiu 來源:互聯(lián)網(wǎng)品牌官01 擦邊少女空降熱搜,幕后推手曝光被網(wǎng)友譽(yù)為&ldquo;純欲天花板&rdquo;的女網(wǎng)紅井川里予,近期因為一組哥特風(fēng)照片登上熱搜,引發(fā)了一場互聯(lián)網(wǎng)世界關(guān)于
  • 攜眾多高端產(chǎn)品亮相ChinaJoy,小米帶來一場科技與人文的視聽盛宴

    7月28日,全球數(shù)字娛樂領(lǐng)域最具知名度與影響力的年度盛會中國國際數(shù)碼互動娛樂展覽會(簡稱ChinaJoy)在上海新國際博覽中心盛大開幕。作為全球領(lǐng)先的科
  • 三星推出Galaxy Tab S9系列平板電腦以及Galaxy Watch6系列智能手表

    2023年7月26日,三星電子正式發(fā)布了Galaxy Z Flip5與Galaxy Z Fold5。除此之外,Galaxy Tab S9系列平板電腦以及三星Galaxy Watch6系列智能手表也同期
  • iQOO 11S評測:行業(yè)唯一的200W標(biāo)準(zhǔn)版旗艦

    【Techweb評測】去年底,iQOO推出了“電競旗艦”iQOO 11系列,作為一款性能強(qiáng)機(jī),該機(jī)不僅全球首發(fā)2K 144Hz E6全感屏,搭載了第二代驍龍8平臺及144Hz電競
  • 電博會與軟博會實現(xiàn)"線下+云端"的雙線融合

    在本次“電博會”與“軟博會”雙展會利好條件的加持下,既可以發(fā)揮展會拉動人流、信息流、資金流實現(xiàn)快速交互流動的作用,繼而推動區(qū)域經(jīng)濟(jì)良性發(fā)展;又可以聚
Top 主站蜘蛛池模板: 六枝特区| 齐齐哈尔市| 策勒县| 冷水江市| 平原县| 德清县| 炉霍县| 石嘴山市| 蒲江县| 延吉市| 肃北| 洪湖市| 峨眉山市| 雅安市| 霸州市| 中方县| 隆德县| 长泰县| 邵东县| 柳江县| 边坝县| 咸阳市| 垫江县| 武功县| 开封市| 黄冈市| 南昌市| 会理县| 鱼台县| 滁州市| 丰宁| 鄂州市| 临汾市| 咸阳市| 讷河市| 库车县| 沂南县| 枝江市| 外汇| 无棣县| 衡东县|