沉默是金,總會發光
大家好,我是沉默
快到年底了,系統開始頻繁出問題。
我有正當理由懷疑:
老闆不想發年終獎,所以開始搞事。
這不,幾年都遇不到一次的 Kafka 消息積壓,
在一個本該安靜下班的夜晚,捲土重來了。
今晚註定是個不眠夜。
原神啓動之前,我先啓動了 Kafka 面板。
-01-
事故現場
事情是這樣的。
我剛下班,正準備洗洗睡,
組裏的小夥伴突然火急火燎地衝過來:
“Kafka 消息積壓一直在漲,預覽圖全出不來!”
我上去一看:
- 原來的 4 個分區:
已積壓 1200+ 條 - 新加的分區:
也開始積壓,而且速度越來越快
第一反應很自然:
是不是消費者處理太慢?那我多加幾個實例不就完了?
於是:
- 加 Pod
- 消費能跑
- 然後……越跑越卡
- 再然後……Pod 開始掛
這時,我的睏意和不祥預感同時達到了頂峯。
-02-
第一層誤判
我突然想起一件事:
Spring Cloud Stream 好像支持併發消費?
於是讓開發老哥把 concurrency 改成 10。
結果呢?
- 消息 積壓更快
- Pod 直接被打爆
- CPU、內存一起飆
這時候才反應過來:
concurrency ≠ 並行處理一條消息
而是:
concurrency = 消費者線程數- 一個線程 = 負責一個分區
- 分區本來就不均勻
- 一加線程,流量傾斜直接拉滿
-03-
詭異現象
我把所有 Pod 日誌拉下來,一條條看。
結果非常魔幻:
- 監聽器日誌:
全部執行成功 - 但同時又出現:
消費超時 - Kafka 面板裏:
Consumer Group 頻繁 Rebalance
我當場愣住。
成功了,又超時?
這是什麼薛定諤的消費?
但作為一個堅定的唯物主義者,我選擇繼續查。
-04-
破案關鍵
問題的答案,藏在 Kafka 的消費模型裏。
你以為的 Kafka:
來一條 → 消費一條 → 確認一條
實際上的 Kafka:
消費者主動一次拉一批 → 處理完 → 才提交 offset
而 Spring Cloud Stream,為了“好用”,幹了件非常容易坑人類的事:
批量拉取,但監聽器只給你一條
假設:
max.poll.records = 500- 每條消息處理 10s
- 處理方式是 串行
- 消費超時時間:
300s
那會發生什麼?
500 × 10s = 5000s
一次 poll,最多隻能處理 30 條
於是就出現了詭異現象:
- 單條邏輯:成功
- 整批消費:超時
- Kafka 認為你“失聯”
- 觸發 Consumer Rebalance
- offset 不提交
- 後面的消息全堵死
我咧個豆。
案子破了。
-05-
兩種解決方案
方案一:立刻止血(適合半夜)
ack-mode: RECORD
效果:
- 每條消息處理完立刻提交
- 不再被批次拖死
- 改一行就能下班睡覺
代價:
- 吞吐量下降
- Kafka 的優勢用不滿
適合:救火、保命、保年終獎
方案二:批量 + 並行(推薦)
思路只有一句話:
批量要小,並行要真
1. 控制批量大小
max.poll.records: 50
2. 自己並行處理這批消息
@StreamListener("<TOPIC>")
public void consume(List<byte[]> payloads) {
List<CompletableFuture<Void>> futures =
payloads.stream().map(bytes -> {
Payload payload =
JacksonSnakeCaseUtils.parseJson(
new String(bytes), Payload.class
);
return CompletableFuture.runAsync(() -> {
// 業務處理
}, batchConsumeExecutor).exceptionally(e -> {
log.error("Thread error {}", bytes, e);
return null;
});
}).collect(Collectors.toList());
// 等待整批完成,再統一提交 offset
CompletableFuture.allOf(
futures.toArray(new CompletableFuture[0])
).join();
}
效果:
- 批次不大,不超時
- 真正並行,吞吐拉滿
- offset 提交穩定
- Kafka 安靜了,世界也安靜了
-06-
總結
這次事故,真正教會我的三件事
1️⃣ Kafka 慢,80% 不是 Kafka 的鍋
是你 消費模型 + 超時配置 + 批量大小 沒想清楚
2️⃣ Spring Cloud Stream 很友好
但越是“像隊列”的封裝,越容易誤導你
3️⃣ 半夜事故,拼的不是手速
而是你對底層機制的理解深度
程序員的深夜,不該白熬
那天問題解決的時候,已經快天亮了。
咖啡喝完了,
Kafka 面板綠了,
飛書安靜了,
我終於能安心睡覺了。
如果你也遇到過:
- Kafka 積壓
- 日誌成功但超時
- Consumer Rebalance 地獄循環
希望這篇文章,能幫你少熬一次夜。
-07-
粉絲福利
我這裏創建一個程序員成長&副業交流羣,
和一羣志同道合的小夥伴,一起聚焦自身發展,
可以聊:
技術成長與職業規劃,分享路線圖、面試經驗和效率工具,
探討多種副業變現路徑,從寫作課程到私活接單,
主題活動、打卡挑戰和項目組隊,讓志同道合的夥伴互幫互助、共同進步。
如果你對這個特別的羣,感興趣的,
可以加一下,微信通過後會拉你入羣,
但是任何人在羣裏打任何廣告,都會被我T掉。