千萬級流量衝擊下,如何保證極致效能

Hello-Brand發表於2024-06-13

1 簡要介紹

隨著網際網路的快速發展,網路應用的流量規模不斷攀升,特別是在電商大促、明星直播、重大賽事、頭條熱搜等熱點事件中,秒級100w請求成為了常態。在這樣的流量衝擊下,如何確保系統穩定、高效地處理每一個請求,為使用者提供極致的體驗,成為了技術團隊面臨的重要挑戰。本文將深入探討在超高流量下如何保證系統的極致效能。

2 架構建設方案

在解決千萬級流量下的流量衝擊問題時,我們需要綜合運用多種技術手段,從系統架構、負載均衡、併發控制、快取策略、資料庫最佳化、限流等多個方面入手。

2.1 系統架構最佳化

系統架構是支撐高併發的基礎。在應對千萬級流量時,我們需要採用分散式、微服務化的架構,將業務拆分成多個獨立的服務,每個服務負責處理特定的業務邏輯。透過水平擴充套件和垂直擴充套件相結合的方式,提升系統的整體處理能力
微服務架構可以參考作者的這個系列的文章《微服務系列
以下是微服務架構簡圖:
image

2.2. 負載均衡技術

負載均衡是實現高併發的關鍵技術之一。透過負載均衡器,我們可以將請求分發到多個伺服器上,實現請求的均衡處理。
常見的負載均衡策略包括輪詢、加權輪詢、最少連線數等。在實際應用中,我們可以根據業務需求和伺服器效能選擇合適的負載均衡策略,來協調多例項服務對每個分片流量分配的需求。
負載均衡可以參考作者的這篇文章《圖解常用負載均衡策略》。
以下是負載均衡器在架構中的位置和職能。
image

2.3 非同步處理與併發控制

透過引入非同步處理機制,我們可以將耗時操作放在後臺執行,避免阻塞主執行緒,提高系統的響應速度。
同時,合理的併發控制也是必不可少的,我們可以利用執行緒池、訊號量等技術手段來控制併發量,避免系統過載。

2.3.1 非同步處理

網際網路場景中經常使用訊息中介軟體進行 非同步處理\削峰 等操作,來緩解系統的壓力。

1. 非同步處理: 處理一項任務的時候,有3個步驟A、B、C,需要先完成A操作, 然後做B、C 操作。任務執行成功與否強依賴A的結果,但不依賴B、C 的結果。
如果我們使用序列的執行方式,那處理任務的週期就會變長,系統的整體吞吐能力也會降低(在同一個系統中做非同步其實也是比較大的開銷),所以使用訊息佇列是比較好的辦法。

登入操作就是典型的場景:A:執行登入並得到結果、B:記錄登入日誌、C:將使用者資訊和Token寫入快取。 執行完A就可以從登入頁跳到首頁了,B、C讓服務慢慢去消化,不阻塞當前操作。

image

2. 削峰: 將峰值期間的操作削減,比如A同學的整個操作流程包含12個步驟,後續的11個步驟是不需要強關注結果的資料,可以放在訊息佇列中。

2.3.2 併發控制

可以透過一些辦法來進行併發控制,如無效請求過濾和加鎖等,避免大量的請求把系統沖垮。

1. Web端/客戶端的超預期請求過濾
大部分的使用者是沒有耐性的,當你的系統因為吞吐過載遲鈍(響應延遲)的時候,使用者可能會反覆的點選按鈕、重新整理頁面來重啟傳送請求。
這樣會對原本就瓶頸的系統造成更大的傷害。最好的辦法就是服務端響應回來或超時之前,對使用者的重複請求無效。
如:限制使用者在5秒之內只能提交一次請求,避免系統過載。

2. 系統入口處(如閘道器接入層)的超預期請求過濾
大部分操作是需要有冪等性保障的。同一個使用者對一個服務批次且持續的請求必然是不正常的,要麼是程式錯誤導致的迴圈請求,要麼是攻擊性行為。
可以根據使用者Id或者使用者的登入Token來識別使用者,避免單位時間內(比如1s)的過量呼叫(比如1000次),透過這種限制來達到控制無效流量的目的。

3. 加鎖進行併發控制

  • 系統程式級別的鎖(如ReentrantLock),保持執行緒池的安全性,避免系統計算量過載
    參考作者這篇:Java核心知識體系8:Java如何保證執行緒安全性

  • 快取層上的分散式鎖,進行流量的有效控制
    參考作者這篇:Redis系列13:分散式鎖實現

  • 資料庫鎖,最底層儲存的資料一致性、有效性保障
    參考作者這篇:資料庫系列:InnoDB下實現高併發控制

這些都是實現併發控制的關鍵機制。透過使用鎖,我們可以確保在併發環境中對共享資源的訪問是同步的,從而避免資料不一致或其他併發過載的問題。

2.4 快取策略

快取是提升系統效能的重要手段。透過快取熱點資料,我們可以減少對資料庫的訪問次數,降低資料庫的壓力。同時,快取還可以提高資料的訪問速度,提升使用者體驗。在實際應用中,我們可以採用Redis等記憶體資料庫作為快取層,透過合理的快取策略實現資料的快速訪問。

Redis官方站點中,有對Redis效能做了比較詳細的壓測,可以參考官方這一篇 How fast is Redis?
在較高的配置基準下(比如 8C 16G +),在連線數為0~10000的時候,最高QPS可達到120000。Redis以超過60000個連線為基準,仍然能夠在這些條件下維持50000個q/s,體現了超高的效能。下圖中橫軸是連線數,縱軸是QPS。
image
下面這張圖為data size 與整體吞吐量之間的趨向關係:
image

快取可以擴充套件閱讀作者的這個系列的文章:★ Redis24篇集合

2.5 資料庫最佳化

資料庫是系統的核心元件之一,其效能直接影響到整個系統的效能。在應對高併發請求時,我們需要對資料庫進行最佳化,包括最佳化SQL語句、建立合適的索引、分庫分表、資料單元化設計等。
透過資料庫最佳化,我們可以提高資料的查詢速度,減少資料庫的負載,從而提升整個系統的效能。
image

資料庫的最佳化可以擴充套件閱讀作者這兩篇文章:
MySQL索引最佳化總結(綜合版)MySQL分庫分表

2.6 流量限流

在流量高峰時段,我們可以透過限流技術來控制請求的速率,避免系統過載。限流的目標是在系統壓力過大時拒絕部分請求,並且failover到固定的響應資訊,保護系統的穩定性。
以令牌桶原理(定速流入)為例,每秒鐘只提供N個令牌,每個請求攜帶一個令牌標識前行,用完即限行。如下圖:
image

限流熔斷可以擴充套件閱讀筆者的這篇文章:微服務治理之限流、熔斷

3 業務場景說明

在實際業務中,高併發的場景多種多樣。以電商平臺為例,在大促期間,大量的使用者會同時訪問平臺,進行商品瀏覽、下單、支付等操作。這些操作都會產生大量的併發請求,對系統的效能提出極高的要求。此外,社交應用、線上遊戲等也面臨著類似的挑戰。

4 總結

在千萬級流量下保證併發請求的極致效能是一個複雜而挑戰性的問題。透過綜合運用系統架構最佳化、負載均衡技術、快取策略、資料庫最佳化等多種技術手段,我們可以有效地提升系統的處理能力和響應速度。同時,我們還需要根據具體的業務場景和效能需求進行針對性的最佳化和調整,以實現最佳的效能表現。
在未來的發展中,隨著技術的不斷進步和業務的不斷擴充套件,我們還將面臨更多的挑戰和機遇。只有不斷地學習和探索新的技術手段和方法,我們才能更好地應對這些挑戰,為使用者提供更加優質、高效的服務體驗。

相關文章