高併發設計_限流

高併發設計

一思路

緩存、降級和限流。

1. 緩存

提升系統訪問速度和增大系統能處理的容量。

2. 降級

當服務出問題或者影響到核心流程的性能則需要暫時屏蔽掉,待高峯或者問題解決後再打開

3. 限流

用來處理前面2種不能解決的情況,比如稀缺資源(秒殺、搶購)、寫服務(如評論、下單)、頻繁的複雜查詢(評論的最後幾頁),因此需有一種手段來限制這些場景的併發/請求量,即限流。


##二限流

操作

###1. 操作
通過對併發訪問/請求進行限速或者一個時間窗口內的的請求進行限速來保護系統,一旦達到限制速率則可以拒絕服務(定向到錯誤頁或告知資源沒有了)、排隊或等待(比如秒殺、評論、下單)、降級(返回兜底數據或默認數據,如商品詳情頁庫存默認有貨)。
###2. 常見的限流
1. 限制總併發數(比如數據庫連接池、線程池)
2. 限制瞬時併發數(如nginx的limit_conn模塊,用來限制瞬時併發連接數)
3. 限制時間窗口內的平均速率(如Guava的RateLimiter、nginx的limit_req模塊,限制每秒的平均速率)
4. 其他還有如限制遠程接口調用速率、限制MQ的消費速率。
5. 根據網絡連接數、網絡流量、CPU或內存負載等來限流。

###3. 注意
1. 好處:不用擔心瞬間流量導致系統掛掉或雪崩,最終做到有損服務而不是不服務;
2. 缺陷: 限流需要評估好,不可亂用,否則會正常流量出現一些奇怪的問題而導致用戶抱怨。

###4限流算法

常見的限流算法有:令牌桶、漏桶。計數器也可以進行粗暴限流實現。


##三令牌桶算法

令牌桶算法是一個存放固定容量令牌的桶,按照固定速率往桶裏添加令牌。
令牌桶算法的描述如下:

1. 假設按照100毫秒的固定速率往桶中添加令牌;
2. 桶中最多存放1000個令牌,當桶滿時,新添加的令牌被丟棄或拒絕;
3. 當一個5個字節大小的數據包(5個請求)到達,將從桶中拿走5個令牌,接着數據包被髮送到網絡上;
4. 如果桶中的令牌不足5個,數據包大於等於5個,且該數據包將被限流,因爲沒有足夠的令牌(要麼丟棄,要麼緩衝區等待)。

在這裏插入圖片描述

##四漏桶算法

可以用於流量整形和流量控制。
漏桶算法的描述如下:

1. 一個固定容量的漏桶,按照常量固定速率流出水滴;
2. 如果桶是空的,則不流出水滴;
3. 可以以任意速率流入水滴到漏桶;
4. 如果流入水滴超出了桶的容量,則流入的水滴溢出了(被丟棄),而漏桶容量是不變的。

在這裏插入圖片描述
##五漏桶算法與令牌桶算法比較

  1. 流入
    1. 令牌桶:固定
      1. 按照固定速率往桶中添加令牌,請求是否被處理要看桶中令牌是否足夠,當令牌數不夠則拒絕新的請求
      2. 允許一定程度的突發:一下子要處理很多請求
    2. 漏桶:任意
  2. 流出
    1. 令牌桶:任意
      1. 允許突發請求,只要有令牌就可以處理,支持拿多個令牌,並允許一定程度突發流量;
    2. 漏桶:固定
      1. 按照固定速率流出:按照固定的速度來處理
      2. 平滑突發流入速率:就是讓高併發的請求按照固定的速度來處理

##六在我們項目中的應用
###1項目的環境
當前我們項目,當用戶登錄的時候,會觸發10多個接口同時請求,當我們服務端向客戶端推送消息後(參與活動有獎勵),大量的用戶(30W)在短時間內登錄我們服務,會造成很大的數據庫和接口請求壓力。當然我們有做了優化。

  1. 一般固定不變的數據預先準備好
  2. 固定數據放緩存
  3. 特性數據(用戶個性化推送數據),預先處理,定時刷新
    ###2使用借鑑漏桶算法
  4. 我們請求來源終端操作,且請求速度是任意的,爲了讓請求不丟失,我們一定要處理來只請求的所有數據,怎麼讓所有的請求不丟失呢,我們先把所有的請求放到阻塞隊列中(桶),開啓多個線程(線程池管理)執行隊列中的任務(固定速度(一個時刻有幾個線程處理任務)處理任務),並返回響應結果。
  5. 後期優化,原先我們處理請求的線程數是固定的,後來我們做了優化,我們對請求的數量做了一個梯度,當超過某個梯度的時候,我們會自動增加線程的數量,當然線程的數量不是可以無限增加的,最大的線程數和cpu,內存有關,當超過我們能處理的最大線程數的時候,我們開啓等待隊列,將所有新的請求放到等待隊列中,同時開啓請求優化服務,將那些請求能個短時間返回結果的請求優先執行,那些要花大量時間的請求,我們對響應的接口做了服務降級。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章