用 《異星工廠》遊戲形象理解Apache Kafka - Ruurtjan

banq發表於2021-11-26

Factorio異星工場 是一個開放世界的 RTS,您可以在其中構建和優化供應鏈以發射衛星並恢復與您的家鄉星球的通訊,而 Kafka 是一個分散式流媒體平臺,它處理非同步通訊一種持久的方式。

我想知道 在 Factorio 和 Kafka 之間的類比開始崩潰之前,我們能走多遠。讓我們從頭開始,通過 Factorio 視覺化探索核心 Kafka 概念,並在此過程中獲得一些樂趣。

用 《異星工廠》遊戲形象理解Apache Kafka -  Ruurtjan

為什麼要打擾非同步訊息傳遞?

假設我們有三個微服務。一種用於開採鐵礦石,一種用於將鐵礦石熔鍊成鐵板,一種用於用這些板生產鐵齒輪。我們可以使用同步 HTTP 呼叫連結這些服務。每當我們的礦機有新的鐵礦石時​​,它都會對冶煉爐進行 POST 呼叫,熔煉爐又會 POST 到工廠。

用 《異星工廠》遊戲形象理解Apache Kafka -  Ruurtjan

從左到右:採礦、冶煉和生產——通過同步通訊緊密耦合

這種設定對我們很有用,直到工廠停電。熔爐的 HTTP 呼叫失敗,導致礦機的呼叫也失敗。我們可以實現斷路器和重試來防止級聯故障和訊息丟失,但在某些時候我們將不得不停止嘗試,否則我們將耗盡記憶體。

用 《異星工廠》遊戲形象理解Apache Kafka -  Ruurtjan

工廠停電

如果只有一種方法可以將這些微服務解耦……當然,這就是 Kafka 的用武之地。使用 Kafka,您可以以容錯和持久的方式儲存記錄流。在 Kafka 術語中,這些流稱為主題

用 《異星工廠》遊戲形象理解Apache Kafka -  Ruurtjan

通過非同步訊息解耦的微服務

對於服務、訊息或記錄之間的非同步主題,在峰值負載和中斷時會被緩衝。這些緩衝區顯然容量有限,所以讓我們談談可擴充套件性

我們可以通過向叢集新增 Kafka 伺服器來增加儲存容量和吞吐量。另一種方法是增加磁碟大小(用於儲存)或 CPU 和網路速度(用於吞吐量)。這些選項中的哪一個為您提供了最佳的價效比取決於用例,但購買更大的伺服器 - 與購買更多伺服器不同- 受制於收益遞減規律。Kafka 的容量隨著每個節點的增加而線性擴充套件,所以這通常是要走的路。

用 《異星工廠》遊戲形象理解Apache Kafka -  Ruurtjan

垂直擴充套件——更大、更昂貴的伺服器

用 《異星工廠》遊戲形象理解Apache Kafka -  Ruurtjan

水平擴充套件——將負載分佈到更多的伺服器上

為了在多個伺服器之間劃分主題,我們需要一種將主題拆分為更小的子流的方法。這些子流稱為分割槽。每當服務產生新記錄時,該服務就會決定該記錄應位於哪個分割槽。

用 《異星工廠》遊戲形象理解Apache Kafka -  Ruurtjan

一個產生記錄的旅行車,一個將訊息放在正確分割槽上的分割槽器,以及一個具有四個分割槽的主題。

在 href="https://github.com/apache/kafka/blob/trunk/clients/src/main/java/org/apache/kafka/clients/producer/internals/DefaultPartitioner.javaL69">預設分割槽雜湊訊息鍵和modulos,超過分割槽的數量:

return Utils.toPositive(Utils.murmur2(keyBytes)) % numPartitions;

這樣,具有相同鍵的訊息總是在同一個分割槽上結束。

請注意,訊息只能保證在生產者和分割槽的上下文中進行排序。來自多個生產者或來自多個分割槽上的單個生產者的記錄可以交錯。

 

如何消費?

現在我們知道了訊息是如何被放到主題上的,讓我們看看它們是如何被消費的。當您開始收聽主題時,預設情況下所有分割槽的記錄都會路由給您。但是,同時執行多個微服務例項以實現更高的吞吐量或可用性是很常見的。如果他們都開始收聽主題,則每個記錄都會被每個例項處理,這通常不是您想要的。

用 《異星工廠》遊戲形象理解Apache Kafka -  Ruurtjan

消費者組允許您在多個消費者之間均勻劃分分割槽。當一個微服務例項加入消費者組時,Kafka 會重新分配一些分割槽給它。同樣,當例項崩潰或因其他原因離開組時,其分割槽將分配給其他例項。Kafka 確保分割槽始終在每個組中的消費者之間平均分配。

用 《異星工廠》遊戲形象理解Apache Kafka -  Ruurtjan

如果某個主題的每個分割槽的記錄數存在偏差,您可能會遇到麻煩。一個例項可能無法跟上,因為它被分配了具有許多記錄的分割槽,而其他例項則處於空閒狀態。您需要確保沒有分割槽的記錄比其他分割槽多得多。

用 《異星工廠》遊戲形象理解Apache Kafka -  Ruurtjan

每個消費者都會跟蹤它已經處理了哪些記錄。由於記錄是按順序處理的,一個簡單的偏移量就足夠了。每隔一段時間(預設為 5 秒),消費者會將其偏移量提交給 Kafka 當一個消費者離開它的組時,它的分割槽被分配給組中的其他消費者。新消費者將能夠從前一個消費者停止的偏移量開始請求記錄。記錄可能已被處理,但尚未提交。您要麼必須從提交的偏移量開始,要麼開始處理新訊息並跳過尚未處理的所有內容。這就是為什麼 Kafka 只能保證訊息至少傳遞一次,或者最多傳遞一次。

 

最後總結

當我們開始複製資料時,這個類比就不再有意義了。使用 Kafka,我們可以多次處理單個記錄。多個消費組可以消費相同的記錄。為了可靠性,主題可以以複製因子為 3 的方式儲存。主題可以有一個保留期,之後記錄將被刪除。所有這一切都是可能的,因為資料與鐵不同,可以輕鬆複製。這是結束這篇文章的好地方。我們已經涵蓋了 Kafka 的所有主要概念,您應該對 Kafka 的工作原理有一個大致的瞭解。

讓我們用一個簡短的回顧來結束:

Kafka 是一個分散式流媒體平臺,通過跨多個伺服器複製記錄以持久的方式儲存記錄。主題由分割槽組成,按順序儲存記錄。分割槽器決定哪些記錄屬於哪些分割槽。消費者組是可選的,有助於在消費者之間分配分割槽以實現可擴充套件性。偏移量作為消費者崩潰時的檢查點提交。

簡而言之,這就是 Kafka 的工作方式。

相關文章