Kafka:磁碟為王的有狀態叢集
· tech
📑 目錄
進入有狀態的重量級,第一個是 Kafka。用體檢表看它,一切都從第②題「狀態」展開——Kafka 的資料(那條可重播的 log)不是抽象概念,它實實在在躺在 broker 的磁碟上。這一個事實,決定了它 infra 面的全部:瓶頸是什麼、怎麼擴、掛了怎麼辦、在 k8s 上怎麼跑。
狀態在磁碟上:磁碟為王
這張圖是 Kafka 一切 infra 決策的根。因為資料在磁碟、且要複製多份,所以:容量的瓶頸是磁碟(retention 設多久、多大,直接換算成要幾 TB);HA 靠 replication——一個 broker 掛,它上面 partition 的 leader 由 ISR 中的 follower 接手,而 acks=all + min.insync.replicas=2 決定「幾個副本確認才算寫成功」,那是持久性與可用性之間的取捨旋鈕。這些全是「因為狀態在磁碟上」延伸出來的。
有狀態的代價:擴縮要搬資料,在 k8s 上要 StatefulSet
有狀態最貴的代價,是擴縮。無狀態的東西加一台就能用;但 Kafka 的資料綁在特定 broker 的磁碟上,擴縮就成了「搬資料」的苦工:
kafka-0/1/2)+ 各自的 PV,重啟後還認得自己那顆磁碟——這正是 stateful 工具在 k8s 上的標準長相容量與監控:盯磁碟、盯 lag、盯副本
Kafka 的體檢,收斂到三個最該盯的地方:
- 容量:瓶頸幾乎永遠是磁碟。
retention.ms/retention.bytes留多久多大,乘上 replication factor,就是你要準備的磁碟總量。磁碟滿了 broker 會出事,所以 retention 要算、要留 buffer。 - 監控三大指標:consumer lag(消費落後 producer 多少筆——最重要,直接反映「消費者跟不跟得上」)、under-replicated partitions(有副本沒跟上同步 = 你的冗餘正在失效,危險訊號)、磁碟使用率。這三個是我看 Kafka 健康的第一排儀表。
- 關鍵旋鈕:
replication.factor(通常 3)、min.insync.replicas(通常 2)、acks、retention.*、num.partitions——這些在 Kafka 維運那篇有更細的展開,這裡從 infra 角度知道「它們決定磁碟用量與持久性」就夠。
反思
Kafka 讓我重新認識了「磁碟」
在碰 Kafka 之前,我對磁碟的印象就是「慢」——所以看到「一個把資料全寫進磁碟的訊息系統,還號稱 High-throughput」時,我是不信的。真正理解它怎麼做到的,顛覆了我的直覺:磁碟慢的是隨機讀寫,順序讀寫其實快得驚人,甚至因為有 page cache 幫忙,常常根本沒真的碰到磁碟。Kafka 就是把「只做順序 append」這個限制,變成了效能的來源。這件事給我的啟發遠超過 Kafka 本身——很多「這東西不是很慢嗎」的直覺,其實是把某一種用法的慢,錯當成了本質的慢。搞清楚一個元件「什麼情況快、什麼情況慢」,比記住「它快還是慢」有用得多。
有狀態的代價,全都藏在「搬資料」這三個字裡
從 infra 角度看過 Kafka,我對stateful 那條軸的體會更具體了:有狀態工具的所有麻煩,幾乎都能收斂成一句「資料很難搬」。加機器要搬 partition、縮容要搬走再下線、換 node 要確保資料還在——無狀態的東西「加一台就好」的輕鬆,在這裡通通不成立。這也是為什麼 Kafka 的 partition 與容量必須一開始就規劃:它不像 stateless 服務可以「先隨便開、之後再調」,因為之後調的代價是搬動 TB 級的資料。有狀態系統的規劃,是一種「先付的稅」——你當下多花的心思,是在替未來省下半夜搬資料的痛。
從 infra 看一個工具,才看得到它「真正的形狀」
我以前學 Kafka,學的是 topic、partition、offset 這些概念;但從 infra 角度重看一遍,才真正認識它——它不是一個抽象的「訊息佇列」,而是一叢吃磁碟、綁磁碟、以磁碟為命的有狀態機器。這個視角的轉換,讓很多原本要死記的規則變得理所當然:為什麼要規劃 partition?因為資料難搬。為什麼在 k8s 要 StatefulSet?因為身分要綁磁碟。為什麼監控盯 under-replicated?因為那是冗餘在失效。當你看見一個工具的「狀態長在哪」,它的整個 infra 形狀就跟著浮現了——這正是這個系列想訓練的那雙眼睛。