欧美成人精品手机在线观看_69视频国产_动漫精品第一页_日韩中文字幕网 - 日本欧美一区二区

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

后端思維之高并發處理方案

freeflydom
2025年4月1日 9:30 本文熱度 225

我有話想說

這篇文章的構思始于2023年,受限于個人經驗與知識積累,初稿拖延至2025年1月才最終完成。在此過程中,許多同行大佬慷慨提供了審稿意見與建議,對此我深表感謝。

這是接近一篇萬字長文,為方便大家閱讀,我整理了文章的大綱并以思維導圖的形式展示。你可以根據自己的興趣點選擇性閱讀,希望這篇文章能為你應對高并發場景提供啟發與幫助。

特別鳴謝:韓楠、王君、杜小非、冼潤偉、鴻庭(排名不分先后)

前言

在互聯網時代,高并發已經成為后端開發者繞不開的話題。無論是電商平臺的秒殺活動、搶購系統,還是社交應用的高頻互動,高并發場景的出現往往伴隨著巨大的技術挑戰。

如何在流量激增的同時,確保系統穩定運行、快速響應?這不僅是對技術能力的考驗,更是對架構設計和資源優化的綜合考量。

在多年的工作實踐中,我有幸接觸并解決了許多高并發場景的實際問題。因此,在這篇文章中,我將結合理論與實踐,深入剖析高并發的本質、應對策略,以及實際案例,希望能夠為你揭開高并發背后的技術奧秘。

文中提到的高并發“標準”三字真言——“砍、緩、多”,以及七大處理手段,均是我在工作中總結出的經驗。這些方法并非涵蓋所有可能的解決方案,但我希望它們能為你提供思路,同時也歡迎大家補充和交流。

什么是高并發?

百度百科:
通俗來講,高并發是指在同一個時間點,有很多用戶同時訪問同一API接口或者Url地址。它經常會發生在有大活躍用戶量,用戶高聚集的業務場景中

簡單的說,高并發是指系統在同一時間內接受到大量的客戶端請求訪問,需要系統(服務端)能夠快速響應并處理請求的能力。在咱們互聯網應用中,例如電商、游戲等在做活動或者促銷的時候,這些熱點業務就非常大可能同時被大量用戶訪問,并造成系統較大的負載。高并發一般伴隨著數據增長、流量增加,這種現象可能是短時間的內的峰值,也可能是持續不斷負載壓力,因此需要開發在架構設計、技術選型、性能監控等多個方面進行優化、調整以提高系統的并發處理能力。

并發與并行的區別是什么?

并發和并行都涉及到同一時刻處理多個任務,但它們的概念和實現方式略有不同。

并發,指的是多個事情,在同一時間段內同時發生了。 并行,指的是多個事情,在同一時間點上同時發生了。

并發,是指一個系統能夠同時處理多個任務或者請求,并且看起來好像這些任務是同時執行的。實際上,這些任務只是在最短時間內交替執行,因為計算機的處理速度非常快,例如在一個 CPU 上同時運行多個應用程序或是處理多個網絡請求。

并行,是指一個系統可以真正意義上同時處理多個任務或請求,因為它有多個執行單元,可以同時執行多個任務或請求。例如在擁有多個 CPU 或多個核心的服務器上,可以同時處理多個請求或任務,這就是并行處理。

雖然兩者一字之差,但是我認為他們屬于不同層面上的概念:

  • 并發屬于是表達了指令發起端到指令執行端的請求情況(系統外部)(系統外部)
  • 并行屬于是描述了系統(應用)執行任務時的模式(系統內部)

高并發的怎樣才算高?

不同的讀者看到這里的時候,心里都會有一個答案:

  • 擁有大項目經歷的同行肯定想,沒個幾十萬、上百萬的QPS都不叫高并發吧?
  • 萌新可能認為,我平常系統峰值最高就兩三千的 QPS,那么起碼也得高一個量級才算吧?

我是這么認為的:

高并發的高并沒有一個具體的量化標準的,并不是必須得多少個萬級別的 QPS 才算是高,因為【高】在物理學里是相對的概念。

對于小型的系統或ToB系統來說,如果初期架構設計沒考慮好或者資源有限,幾百上千的 QPS 的并發訪問可能已經會對系統造成一定的壓力;

對于大型互聯網公司或應用,每秒鐘數萬甚至數十萬的并發訪問甚至峰值達到百萬級這都并不罕見。

因此,在討論高并發時,我們不必將其想象為極端數量級的并發情況。關鍵在于理解特定業務場景下,在何種條件(包括人力、技術力、計算力)下,為了達到既定目標(如穩定性、安全性、用戶體驗)而需要處理的并發量

基于這些因素,當并發量達到一定水平,足以影響這些目標時,我們通常將這種情況視為高并發。這樣的判斷并不僅僅基于并發量的增加是否達到了某個具體的“高并發”標準。

高性能等于高并發嗎?

首先,高并發與高性能之間確實存在直接的聯系。高性能指的是系統或應用程序能夠迅速處理單一請求的能力,這意味著在相同的時間內,一個性能更優的系統能夠處理更多的請求,從而提升其并發處理能力。

以一個系統接口為例,假設它在單線程環境下能夠達到每秒100次查詢(100QPS),這意味著處理單個請求的時間大約是0.01秒。如果我們將處理速度提升十倍,即每個請求的處理時間縮短到0.001秒,那么理論上的QPS可以提升到1000QPS。這個例子清晰地展示了高性能與高并發之間的正相關性。

然而,高性能與高并發并非完全等同

  • 高性能關注單個請求的處理效率,
  • 高并發關注系統同時處理大量請求的能力。

一個系統即使設計之初就考慮了高并發,能夠同時接收大量請求,但如果單個請求的處理時間較長,其響應速度和整體性能可能仍不理想。

例如,某接口通過隊列異步處理請求,雖然能應對高并發,但如果隊列設計不合理或任務本身耗時較長(如5-8秒),會影響用戶的實時體驗。

綜上所述,盡管高性能與高并發緊密相關,它們并不是同一概念。實際上,高性能的解決方案可以視為高并發解決方案的一個重要組成部分,但高并發系統的設計還需綜合考慮分布式架構、緩存、限流等技術,以優化整體性能和用戶體驗。

不滿足高并發會有什么后果?

在高并發環境下,如果系統不能有效處理大量并發請求,可能會導致多種嚴重后果,影響系統的性能和用戶體驗。

下圖是系統在高并發場景下不同的層面的后果表現:

然而我們后端開發關注的層面更多是偏向于接口、數據庫還有服務器層面,因此我根據上圖我重新篩選與整理了一份詳細的表格如下:

層級

類型

問題

描述

應用層

性能下降

響應時間增加

當系統無法處理高并發請求時,響應時間會顯著增加,用戶需要更長時間才能得到反饋

吞吐量降低

系統的整體吞吐量(每秒處理的請求數)會減少,無法充分利用硬件資源

數據庫

鎖爭用和死鎖 

鎖爭用

在高并發環境下,多個事務可能同時爭用相同的資源,導致鎖爭用問題,影響事務的執行

死鎖

高并發情況下,多個事務可能相互等待對方釋放鎖,導致死鎖,進而導致事務無法完成

數據不一致

數據競爭

高并發請求可能導致數據競爭問題,多個請求同時修改相同的數據,導致數據不一致

臟讀、不可重復讀和幻讀

在高并發環境下,事務隔離級別不足可能導致臟讀、不可重復讀和幻讀等問題,影響數據的正確性

服務層

資源耗盡  

CPU過載

高并發請求可能導致CPU使用率過高,影響系統的整體性能

內存耗盡

大量并發請求可能導致內存耗盡,尤其是在沒有進行有效的內存管理和優化時

磁盤I/O瓶頸

頻繁的磁盤讀寫操作可能導致磁盤I/O瓶頸,進一步影響系統性能

服務器崩潰

服務器過載

高并發請求可能導致服務器過載,最終導致服務器崩潰或宕機,無法提供服務

資源泄漏

未正確釋放的文件句柄、數據庫連接、網絡連接、鎖資源等會致系統性能下降,甚至系統崩潰

 

有哪些通用的高并發方案?

通過上述我們清楚的了解到高并發處理不當的嚴重性,那么究竟有沒有拿來即用的方案直接套上去就可以解決了呢?

有,我把過往的經驗總接了一下,從大方向來看一共三大類:限流、異步、冗余。

這三個詞,我相信大家都不陌生,我也給他們都各用一句話來描述。

  1. 限流,溢出的流量就不要了
  2. 異步,不著急的任務就放緩處理
  3. 冗余,弄多幾個副本分擔壓力

因此,高并發的通用解決方案我認為無疑就是三字真言:砍、緩、多

每個類型其實又細分共七大處理手段,我整理了一張表格給到各位,毫不夸張說,從我過往經驗來看,以下方案可以解決我們日常遇到90%的并發問題。

類型

方案

描述

限流

業務限流

根據具體業務場景進行限流,例如搶購前答題、活動過量時限購。

技術限流

使用算法在應用層面(API網關)進行限流,例如基于漏桶、令牌桶算法等限流。

異步

調度任務

先把數據暫存下來,定期或者特定條件下(閑時)進行批量的處理

消息隊列

削峰:將瞬時高峰流量平滑處理,使得后臺服務可以按照自己的處理能力逐步處理消息,從而避免系統崩潰

異步化:系統可以將需要長時間處理的任務(如視頻、音頻處理、數據分析等)異步化,避免主線程阻塞,提升系統的響應速度和用戶體驗

冗余

集群

負載均衡:通過多個服務器節點分擔壓力,避免單個服務器壓力過載。不局限于API應用,也可以是數據庫一主多從

故障轉移:如果集群中的某個節點發生故障,負載均衡器可以將請求重新分配給其他健康節點,從而保證服務的連續可用

緩存

把熱數據存放到高性能存儲系統進行讀寫處理,以此降低數據庫訪問量,提高系統響應速度。

靜態化

將動態產生的數據保存成靜態文件,或者將固定計算規則數據事先計算好存放。從而降低系統的計算負荷和數據庫訪問壓力。

例如 介紹頁靜態化、報表數據靜態化。

 

 三字真言,七大處理手段固然好使,但是并不代表可以濫用,像限流、集群、緩存等更多屬于短期收益高的應急手段。

舉個例子,可能我們的問題其實就是一個慢查詢導致的數據庫負載過高,從而影響了應用的工作線程數阻塞,最后影響到了應用服務器的CPU過載從而導致接口無法響應,這種情況下我們貿然的去堆硬件、加緩存而不去優化語句,這無疑是飲鴆止渴,還會額外增加成本(硬件、維護)。

如果本質問題未得到根本解決,問題終將再次出現,時間只是決定它重現的變量。

高并發有哪些場景?

從大層面來看,高并發場景可以分為“讀”和“寫”兩類。以典型的互聯網系統為例,讀寫比例通常為 8:2,即讀多寫少。因此,讀寫場景各自具有不同的特點,采用的優化方案也有所區別。

讀場景

在互聯網應用中,系統通常可以看作是一個資源整合的平臺,因此讀操作占據了較大的比例。無論是數據庫還是接口,讀操作一般具有以下兩個特點:冪等性和負載均衡性(除非接口設計得不合理,如讀寫混合的情況)。

冪等性指的是:
相同的參數調用同一個方法,無論執行一次還是多次,響應的結果都是一致的。將這一概念應用到讀場景中,意味著對于相同的輸入參數、相同的處理邏輯,最終返回的結果始終一致

負載均衡性

讀操作由于具備天然的冪等性,API 服務通常傾向于設計為“無狀態”。這種設計使得在面臨負載瓶頸時,可以通過增加服務副本實現橫向擴展(Scale-Out),無需引入復雜的邏輯處理。此時,系統的關注點更多集中在數據庫(存儲系統)和服務器的性能及負載上。

眾所周知,關系型數據庫在處理分布式寫(例如分庫分表)時面臨較大的挑戰,但在分布式讀方面具有天然優勢。成熟的數據庫通常能夠通過簡單的組件實現一主多從架構,支持讀寫分離。

無論是接口層面的服務集群,還是數據庫層面的一主多從架構,其核心策略都在于通過【】副本來分擔壓力,提升性能與可用性。

然而,這種場景通常假設數據是靜態的,不涉及復雜的計算。當面對復雜計算的高并發場景時,數據庫(存儲系統)的負載壓力會更加明顯。

優化手段

為應對上述問題,可以引入以下優化手段:

1. 緩存:將熱數據存儲在內存(Redis)中,減少對數據庫的直接訪問。

2. 靜態化:將動態生成的數據轉換為靜態(如 HTML 文件、中間表數據),在一定時間內復用熱數據。

無論是增加服務副本,還是使用緩存和靜態化手段,其核心思想都是一致的:冗余。通過冗余數據或資源,減少系統在高并發場景下的負載壓力。

寫場景

相比讀操作,寫操作在高并發場景下更復雜,因其缺乏天生的數據冪等性和負載均衡。寫操作的優化主要圍繞數據一致性、高性能異步處理展開。

異步處理

異步處理在高并發的寫場景中是最直接有效的,其核心思想采用【】的策略。隊列和調度任務在這里扮演了兩個關鍵角色:緩沖和延緩

  • 隊列:可作為數據的臨時存儲區域,隊列將高并發的寫操作轉化為串行處理(或少量并行),從而起到緩沖作用,有效減輕后端系統的瞬時壓力。例如:數據采集
  • 調度任務:通過控制處理頻率(速度和時間),調度任務將非實時性強的操作延遲處理,并在流量低峰期集中批量執行,從而實現流量的平滑化。例如:排行榜、季度報表等

然而,異步處理并非萬能,存在一定的場景局限性。并不是所有的寫操作都適合使用隊列。例如,對于時效性要求較高的請求,異步處理可能無法滿足需求,此時需要采用一些特殊手段來彌補,例如輪詢查詢、WebSocket 推送等實時機制。

高性能寫

在高性能存儲場景中,NoSQL —— Redis 是常見的選擇。一個典型的應用場景是搶購系統,其中針對高并發寫操作的解決方案通常采用“預扣減”策略。其處理流程如下:

  1. 數據同步:通過后臺服務或定時調度任務,將數據庫中的庫存數據提前同步到 Redis。
  2. 庫存判斷:通過 Redis 實現庫存的快速判斷。
  3. 扣減操作:每次對熱門商品的庫存進行扣減時,直接在 Redis 中使用 INCR -N 指令完成。

這種方法有效避免了數據庫在高并發寫入場景下因鎖機制導致的性能瓶頸,同時充分利用 Redis 的高吞吐能力,顯著提升了系統的響應效率。

限流

在互聯網領域,流量被視為至關重要的資源,因此有一句話廣為流傳:“流量為王”,因為流量直接關系到用戶接觸度和潛在的商業價值。

盡管流量的增加在理論上是有利的,但在資源有限的現實環境中,過量的流量可能會成為系統的負擔,甚至導致系統崩潰。

因此,為了避免系統因流量激增而超出承載能力,我們通常采用限流策略,其核心思想是通過“砍”的方式對流量進行控制。限流策略可以分為技術限流業務限流兩種方式。

技術限流

技術限流通過技術手段對訪問流量進行控制,確保系統在其負載能力范圍內平穩運行。通常,這類限流措施會在流量入口(如 API 網關)處實現。常見的技術限流策略包括:

  • 速率限制(Rate Limiting):限制用戶在單位時間內的最大請求次數。
  • 令牌桶(Token Bucket):通過令牌分發機制控制請求速率,允許一定程度的突發流量。
  • 漏桶(Leaky Bucket):將請求以固定速率排出,平滑流量波動。
  • 熔斷器(Circuit Breaker):在系統檢測到異常或過載時,主動中斷請求鏈路,保護系統免于崩潰。

業務限流

業務限流從業務層面出發,通過調整業務策略來控制流量,不僅可以減輕系統負擔,還能優化用戶體驗。常見的業務限流策略包括:

  • 用戶分級服務:根據用戶等級或類型實施差異化的訪問策略,例如,VIP 用戶享有更高的請求優先級或更大的訪問額度。
  • 預約機制:針對流量激增的場景,通過預約制度控制用戶訪問。例如,在特定時間段內限制服務人數,分批次提供服務。

我遇到的高并發優化場景

在之前的討論中,我們探討了許多高并發場景的理論知識。接下來,我將分享一些實際工作中的優化案例。

無狀態讓API服務"力大飛磚"

多年來,我司主要通過 Redis 和 服務集群 來優化系統性能。隨著用戶數量和日活躍度的持續增長,API服務的CPU壓力逐漸增大。為應對這一挑戰,我們從設計之初便采用了 無狀態服務,并引入 Nginx 實現負載均衡,使服務能夠根據流量需求進行 橫向擴展,從而實現集群化部署。

問題背景

近期,由于合作方投流,平臺流量進一步增長,特別是在晚高峰時,部分API服務節點出現滿負載情況,而數據庫負載卻保持正常。通過監控和代碼分析發現,問題出在某些接口的實現上。這些接口每次讀取大量數據,并通過 Foreach 進行逐條查詢和計算。由于查詢是基于主鍵的,數據庫壓力不大,但數據量過大直接導致單次請求執行時間過長。當晚高峰多名用戶并發請求時,這些接口瞬間占滿API服務的工作線程,導致 CPU負載飆升。

臨時應對

為應對流量高峰,我們通過 API橫向擴容 的方式,臨時增加了多臺節點機,緩解了服務壓力,確保平臺能夠穩定運行,抓住這波流量。

緩存很有用,但姿勢要對

為了優化性能,我們幾乎對所有核心業務(如首頁數據、推薦位、排行榜、作品內容等)都采用了 緩存策略

這種方法在過去幾年中效果顯著:只要出現性能瓶頸,引入緩存幾乎總能解決問題。尤其是首頁業務,這類數據通常是每隔數小時更新一次的偽靜態數據,使用緩存完全合理。

然而,這也引出了一個值得思考的問題:緩存是否能解決所有性能問題?

緩存雖然能夠顯著提升數據讀取性能,但對于復雜計算、接口設計缺陷以及高并發場景下的線程占用問題,緩存并非萬能。我們需要結合具體場景,從代碼優化、接口設計、數據庫查詢效率等多方面入手,才能真正解決性能瓶頸。

在一年的最后一天,我們發現了一個嚴重問題。12月31日午夜12點,咱們數據庫的CPU使用率突然從20%激增至100%。通過檢查接口日志和數據庫阻塞日志,問題鎖定在一條長期使用的排行榜SQL語句。按理說,這部分數據應有緩存,為何系統會崩潰?經過代碼審查,問題如下:

問題分析

偽代碼如下:

// 緩存策略模式 - cache-aside
var redisKey = "rankinglist:" + DateTime.Now.ToString("yyyyMMdd");
var rankingListCache = redis.Get(redisKey); // 從緩存獲取數據
if (rankingListCache != null)
    return rankingListCache;
var data = db.RankingList.GetList(); // 從數據庫獲取數據,復雜查詢
if (data.Any())
{
    redis.Set(redisKey, data, 3600); // 寫入緩存
    return data;
}
return new List();

1. 緩存鍵設計問題

緩存鍵基于 DateTime.Now.ToString("yyyyMMdd") 生成,導致跨年、跨月、跨日時,年度榜、月榜、周榜在午夜12點立即失效,觸發所有請求直接訪問數據庫。

2. 緩存穿透問題

僅當 data.Any()`為真時才會更新緩存。如果數據庫查詢結果為空,則不會寫入緩存,導致每次請求都直接訪問數據庫。

臨時優化

針對上述問題,我們進行了以下優化:

var redisKey = "rankinglist:" + type; // 改為基于榜單類型的緩存鍵
var rankingListCache = redis.Get(redisKey); // 從緩存獲取數據
if (rankingListCache != null)
    return rankingListCache;
var data = db.RankingList.GetList(); // 從數據庫獲取數據
if (data.Any())
{
    redis.Set(redisKey, data, 3600); // 緩存有效數據
    return data;
}
else
{
    redis.Set(redisKey, new List(), 60); // 緩存空數據1分鐘
    return new List();
}

1. 緩存鍵設計優化

   去掉基于日期的緩存鍵,改為按榜單類型(如年度榜、月榜、周榜)生成緩存鍵,避免因日期變更導致緩存大規模失效。

2. 緩存穿透防護

   即使數據庫查詢結果為空,也緩存空數據(有效期1分鐘),避免頻繁查詢數據庫。

通過以上優化,臨時解決了Redis引發的緩存穿透和緩存雪崩問題。

長期優化

從數據庫架構設計角度,我們進一步采取了 主從分離策略,將首頁只讀業務和復雜查詢遷移至從庫。遷移后,通過 Zabbix 監控發現,主庫CPU負載高峰現象徹底解決,主庫負載降低了50%,主從庫運行穩定,性能大幅提升。

異步與靜態化

一個工作日的早晨,系統再次報警,部分用戶反饋無法訪問平臺功能。問題持續約 20 分鐘后逐漸恢復。通過日志和監控分析發現,問題源于從庫 CPU 負載達到 100%,由類報表功能的復雜查詢引發。

前一天啟動的活動吸引了大量用戶次日參與,但部分緩存失效導致相關功能查詢直接落庫。由于查詢語句執行時間較長(5-10 秒),結果無法及時寫入 Redis,后續用戶的請求均直接查詢數據庫,導致 CPU 瞬間飆升至 100%。這種現象稱為緩存擊穿。高并發下的查詢超時進一步加劇了無法緩存的情況,形成惡性循環

得益于主從分離策略,本次僅部分功能受影響,但復雜查詢在高并發場景下對數據庫負載的壓力較大,亟需優化。

考慮到相關數據短時間內不會變化,我們對架構進行了調整:

  1. 靜態化數據處理:將實時 SQL 查詢改為通過調度任務定時執行,將查詢結果壓縮后存儲至中間表。
  2. 接口調整:修改接口邏輯,直接從中間表讀取數據。

這種策略有效降低了數據庫對復雜查詢的計算壓力,同時顯著提高了接口的并發處理能力。

復雜 SQL 在高并發場景下對數據庫影響較大,尤其配置不足時更易成為瓶頸。通過靜態化處理和中間表設計,既緩解了數據庫壓力,又優化了用戶體驗。

限制不住,就扛下來

俗話說:“人怕出名,豬怕壯”隨著平臺不斷發展壯大,關注度提高的同時,挑戰也隨之而來,如盜版和競爭對手使用爬蟲抓取數據。這些爬蟲不僅可能將商業數據發布到免費網站,損害平臺利益,還會通過頻繁請求導致系統壓力激增。

雖然“流量為王”,但惡意爬蟲的流量對平臺毫無價值。為此,我們迅速在網關層面實施限流策略,從 IP、Cookies、UA 等多個維度限制密集請求,有效應對了基礎、粗暴的爬蟲攻擊。

然而,某日搜索庫服務器 CPU 使用率驟然飆升。分析后發現,黑客通過模擬客戶端身份并以分布式方式繞過限流策略發起攻擊。為長期防御此類問題,我們需要從前后端入手,增加校驗規則、更換密鑰、加強客戶端防護等多方面提升系統安全性。

但我們也深知,沒有絕對完美的安全策略,后端服務必須具備一定的抗壓能力。

非常遺憾的是,我們用Like做搜索作為技術債務保留了下來,也是這次事故的兇手,為解決這一問題,我們引入了 ElasticSearch,通過定時任務定期同步搜索庫數據至 ElasticSearch,并調整接口邏輯指向 ElasticSearch。這一優化顯著提升了搜索性能,使系統在高并發場景下更穩定,也更從容地應對爬蟲流量攻擊。

怎么應對火熱搶購?

雖然我們公司主營文娛類業務,但任何形式的優惠或免費活動都能吸引大量用戶,類似電商平臺的搶購活動。

以平臺推出的福利商城為例,用戶通過完成任務或參與活動獲得虛擬幣,用于兌換“代券”免費觀看作品。代券每天限量,每晚12點系統自動刷新庫存,開啟新一輪兌換。

在一次五一活動中,我們吸引了大量用戶參與。然而活動結束后的第二天凌晨,主庫 CPU 負載突然飆升至 100%,持續約 15 分鐘。經過分析發現,問題出在用戶集中搶兌代券時,SQL 執行遇到高并發鎖競爭。盡管庫存扣減的 SQL 語句很簡單:

UPDATE TableA SET Stock = Stock - 1 WHERE Stock > 0;

問題的根源在于并發環境下共享數據產生的鎖競爭。

鎖競爭的高負載原因:

1.自旋鎖的忙等
自旋鎖在鎖被占用時,線程會不斷循環嘗試獲取鎖而不掛起,導致CPU持續執行無效操作,顯著增加CPU負載。
2.頻繁的上下文切換
高并發下,線程競爭鎖未果時會被掛起并進入等待隊列,鎖釋放后再被喚醒。頻繁的掛起和喚醒引發大量上下文切換,消耗CPU資源,提升負載。
3.死鎖檢測的開銷
在高并發場景中,數據庫或操作系統需要掃描等待圖或事務依賴關系以檢測死鎖,這種復雜計算會顯著增加CPU負擔。

為解決這一問題,我提出了兩種優化方案:

  1. 調整庫存刷新時間
    建議將庫存刷新時間改為凌晨 4-5 點的低峰期,避開用戶集中“蹲點”兌換的高峰時段。這是成本最低的解決方案,但團隊認為用戶已習慣現有模式,調整可能影響用戶體驗。
  2. 預扣庫存方案
    針對高并發問題,設計了基于 Redis 的預扣庫存機制:
    1. 庫存同步至 Redis:后臺對熱門商品新增或編輯時,將庫存同步到 Redis。
    2. Redis 扣減邏輯:客戶端請求兌換時,系統先檢查 Redis 中的庫存,若庫存量大于 0,使用 INCR 命令扣減庫存。只有扣減成功,才生成兌換記錄。
    3. 庫存回寫數據庫:當 Redis 庫存扣減至 0 時,將庫存同步回數據庫,并更新庫存狀態供客戶端展示。

通過 Redis 的高性能讀取和寫入操作,避免了數據庫的鎖競爭問題,同時顯著降低了 CPU 負載。

搶購可以使用隊列處理么?

針對“搶購”類業務場景,可以考慮引入隊列機制來緩解熱點數據更新導致的高負載問題。隊列的先進先出(FIFO)特性和串行處理機制能夠有效降低數據庫壓力,避免高并發寫入引發的性能瓶頸。然而,隊列的引入往往意味著異步處理用戶請求,這對需要即時反饋的場景帶來了新的挑戰

例如,類似【智行火車票】APP的排隊下單系統(盡管未明確其是否使用隊列),其邏輯與隊列機制非常相似:

  1. 用戶下單后進入排隊頁面(中間頁),頁面通過定時刷新更新訂單狀態。
  2. 處理完成后,頁面展示支付按鈕供用戶操作。
  3. 支付完成但尚未出票時,用戶會跳轉到訂單詳情頁,出票后則以通知形式告知用戶。

再舉個例子,以上面說的福利商城的“搶購”業務為例:

  1. 用戶點擊【兌換】按鈕后,系統將請求放入隊列中,隊列逐步消費這些請求。用戶此時會進入一個中間等待頁面,等待兌換結果。
  2. 由于并發情況下庫存數據未能實時同步扣減,最終兌換結果可能失敗。
  3. 對于結果通知的方式,可以選擇通過 WebSocket 實時推送,也可以在中間頁由客戶端輪詢獲取結果。

 

然而,這種改造方式需要前后端協同配合,且需要調整用戶交互邏輯,改造成本相對較高。

針對“搶購”類業務場景,優化方案有多種選擇。具體方案應根據系統的實際體量和業務需求,選擇最優的處理方式。

隊列適用場景分析

在我們的平臺上,隊列適用于以下寫入場景:

  1. 客戶端行為日志采集
    用戶操作頻繁、請求量大,但對響應時間要求不高。日志采集主要用于生成報告供內部分析,因此無需實時寫入數據庫。通過隊列異步處理,可有效緩解高并發寫入壓力。
  2. 個推數據處理
    個推數據雖需基于用戶行為進行實時推薦,但本質上是偽實時場景。推薦算法的響應時間通常在 0.01 秒到 3 秒之間波動,當無法即時生成推薦結果時,可使用公共推薦庫作為替代。隊列能夠將推薦計算轉移至后臺,分散系統壓力,提升整體性能。
  3. 公共數據統計
    用戶觀看廣告后,平臺會贈送代金券,同時廣告的總觀看次數需要更新。在晚高峰時,大量用戶集中操作會對廣告數據表造成寫入壓力,甚至引發鎖競爭或死鎖問題。為優化性能,可將“廣告觀看次數 +1”的操作通過消息隊列(MQ)異步處理。用戶領取獎勵后,系統將更新請求寫入隊列,由后臺異步更新數據庫,避免高并發直接寫入。

高并發不是終點

高并發不是終點,而是一場持續的“攻防戰”。優化高并發系統需要從技術與業務雙重角度出發,既要平衡用戶體驗、系統性能與資源成本,又要根據具體場景靈活應用各種策略。無論是三字真言“砍、緩、多”,還是七大處理手段,都沒有絕對的萬能解法——正如軟件工程的經典原則所言:【沒有銀彈】。真正的高并發優化核心,不僅在于提升系統性能與穩定性,更在于如何在有限的資源條件下,以最優成本滿足業務需求。

高并發不是終點,而是開發者不斷突破技術邊界的新起點。希望本文的經驗與總結,能夠為你應對高并發場景提供啟發與幫助。


該文章在 2025/4/1 9:30:16 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved