> 千萬級推送不僅考參數調優,更考架構防禦!本文拆解 1000 萬簡訊 1 小時發完的真實現場:從 N_threads = N_cpu × U_cpu × (1 + W/C) 黃金公式,到動態監控調優,再到防止 OOM 的「生產級」拒絕策略。文末附帶 P7 級面試套路模板,助你掃平執行緒池深坑。
寫在開頭:
前兩天有個在大廠搬磚的兄弟找我吐槽,說面試掛在了「執行緒池」上。
面試官沒問那些死記硬背的原理,直接丟了一個業務題:
「我們要發 618 行銷簡訊,1000 萬條,要求 1 小時內發完。你打算怎麼設計執行緒池?核心參數給多少?拒絕策略選哪個?」
這哥們沒多想:「簡單啊,算一下 1 小時 3600 秒,每秒發 2800 條。直接搞個 FixedThreadPool,執行緒數開到 500,隊列給大一點不就行了?」
面試官冷笑一聲,連追三問:
FixedThreadPool 預設隊列是 LinkedBlockingQueue,長度是 Integer.MAX_VALUE(近似無界),千萬級資料還沒發完,記憶體就 OOM 了,你負責?」他瞬間原地石化。
其實,這道題考的是「高併發下的資源掌控力」。今天 Fox 帶你拆解執行緒池的 3 種實戰境界。
Executors 是生產環境的「禁區」?在大廠規範裡,嚴禁使用 Executors.newFixedThreadPool 或 newCachedThreadPool。
Integer.MAX_VALUE 的任務數量。在 1000 萬資料的衝擊下,還沒等到執行緒處理,你的 JVM 堆記憶體就先爆了。CachedThreadPool 允許創建的執行緒數也是無上限,瞬間的高併發能直接把 CPU 100% 跑滿,甚至耗盡系統資源。Fox 的結論:生產環境必須手動建立 ThreadPoolExecutor,且必須配合有界隊列(bounded queue)。
面試官問你執行緒數給多少,千萬別直接說 200 或 500。你要先問:「這任務是 CPU 密集型還是 IO 密集型?」
簡訊推送涉及網路呼叫,屬於典型的 IO 密集型。
根據經驗公式:
N_threads = N_cpu × U_cpu × (1 + W/C)
實戰落地:對於千萬級推送,通常 W/C 很大,建議初始執行緒數設為 2 × N_cpu 起步,並根據壓測結果調整。
參數是「死」的,流量是「活」的。大廠 P7 的標準做法是:使用「動態執行緒池」。
Fox 提示:業界著名的開源專案 Hippo4J 或 DynamicTp 就是做這件事的,面試時提一句加分不少。
當 1000 萬資料湧入,執行緒池滿了,拒絕策略(RejectedExecutionHandler)選哪個?
AbortPolicy(預設):直接丟出例外,千萬別選,資料直接丟失。CallerRunsPolicy(推薦):讓提交任務的執行緒(例如撈資料的執行緒)自己去執行。這其實是一種「天然的背壓(Backpressure)」。提交端自己去發簡訊,就沒空再去資料庫撈新任務,從而減緩任務產生速度,給執行緒池喘息的機會。很多人應該還記得我寫過:CallerRunsPolicy(回退給呼叫者執行)是個坑,因為它會阻塞主執行緒。但!在千萬級推送這種「離線批量場景」下,這個「坑」反而成了神技。
CallerRunsPolicy,讓「撈資料的執行緒」自己去發簡訊。面試官看你答得不錯,通常會祭出最後一招:「任務在記憶體隊列裡,機器當掉了,100 萬條簡訊沒發出來,怎麼補救?」
滿分回答:
「針對 1000 萬簡訊推送,我不會使用 Executors 快捷建立,因為無界隊列有 OOM 風險。
第一,參數設定:我會基於公式進行壓測,由於是 IO 密集型,初始執行緒數設為 2 × N_cpu 起步,並通過壓測微調。
第二,拒絕策略:我會選 CallerRunsPolicy。它能透過『背壓』機制,讓提交端在任務過載時參與處理,從而限制任務的生產速度,保證系統不崩。
第三,動態化:為了應對簡訊供應商波動,我會接入動態執行緒池框架,實時監控隊列積壓情況並動態調整核心執行緒數與隊列大小。
第四,可靠性:結合資料庫狀態位與定時補償任務,確保即便機器重啟,任務也不會丟失。」
聊到這裡,肯定有人會問:「Fox,單機執行緒池調優我懂了,但如果 1000 萬任務發到一半,機器當掉了怎麼辦?如果是 1 億資料,單機頻寬和 CPU 根本吃不下呢?」
這正是大廠面試官最喜歡的「奪命連環炮」。
在真實的生產環境下,我們絕對不會把雞蛋放在一個籃子裡。單機調優是「術」,集群架構才是「道」。
現在的互動問題來了:
面試官追問:「現在給你 5 台機器組成的集群,你如何設計一套架構,保證這 1000 萬條簡訊在 1 小時內『不重複、不遺漏、高併發』地發出去?」
提示幾個思考維度:
歡迎在評論區留下你的設計思路!
寫在最後
技術面試拼的不是死記硬背的參數,而是你對「系統穩定性」的敬畏之心。能提前預判 OOM 風險、考慮到背壓問題、兼顧資料可靠性,這才是你和普通開發者拉開差距的關鍵。
覺得有用的兄弟,按讚+收藏,面試前翻一翻,直接避開坑、穩拿分!
想吃透更多高頻面試題、避開面試地雷?可以關注公眾號【Fox愛分享】!我整理的面試寶典已更新至 200 多萬字,光高併發、分散式的專案場景題就有幾百道,全是面試剛需,需要面試的同學直接自取,幫你少走彎路、快速上岸~