前言
簡單整理一下分發的基本思路。
正文
kafka 原本是做日誌管理系統,主要是分發這塊的。
那麼如何做分發呢?
分發的是什麼呢? 分發的其實是日誌,日誌是事件狀態,kafka 內部就叫做Record,也就是記錄哈,也可以叫做事件狀態的記錄,其實和日誌的意思差不多了。
首先需求是有分類的,要給record 進行分類,這個分類就用topic。每個分類有自己的topic。
然後就是怎麼存的問題了。
首先最容易想到的是下面這種:
一個佇列,往佇列裡面存就好,然後另外一端進行消費就好。
這樣又一個問題,那就是分發的需求是不止能分發一個,還要分發很多個消費者。
那麼就不能是佇列,因為佇列消費掉就沒了。
那麼想到的就是陣列。
為什麼是陣列呢?
因為陣列有索引,多個訊息者要需要記住自己消費到什麼地方了。
這個就是消費者位移,表示消費者的消費進度,每個消費者都有自己的消費者位移。
有了這個消費者位移後,消費者得告訴自己叫什麼吧,消費者不得給個名字啊,不然誰知道呢?
那就變成了上面這樣。
似乎這樣就能滿足需求了。
然後執行起來發現一個問題,那就是生產在大多數情況下,是會形成堵塞的。
因為這樣還是一個可能多個生產,但是一個消費的情況。即使生產一個,消費一個(這裡只消費名相同),那也肯定是達不到,因為報告一件事情容易,解決一件事情困難。
那麼能不能這樣呢?
那麼下一個想法就是能不能增加消費速度呢?
上面就是有多個consumer name 為consumer1的同時進行消費。
這裡且不管實現難度哈,單純概念。假如有多個consumer1 可以同時進行消費,且不會消費到相同的,這樣就增加了消費速度。
那麼這就是一組consumer,那麼得給這個組改個名字,叫做consumer group。
這樣似乎是沒有問題了,雖然這樣實現比較複雜,但是能實現。
上面這種想法也是能實現的,比如說有一個consumer group 裡面的取個一條資料,已經消費的標記為消費,如果消費了,offset 繼續偏移就好,不需要消費。
但是這樣有一個問題,這裡不談及到任何實現困難上,那就是不能保證消費順序。
在現實中我們收到的新聞是有時間順序的,但是這樣消費的是沒有順序的。
比如說,最近俄烏戰爭,加入你先收到的是俄烏戰爭結束了,然後收到俄烏戰爭開始了,懵逼不。(講過實際中的例子,如果無法保證消費順序的話,比如說一個命令是開機一個命令是關機,使用者執行的是先關機再開機,那麼如果開機和關機命令是相反的,可想而知效果完全不同)
這是不是很不科學啊。所以這樣做是不符合現實世界的,計算機世界現在是幫助我們解決現實世界的問題。
這樣是不符合需求的。那麼既然,消費者增加不可靠,那麼可以這樣。
那就按照上面這樣,增加topic,細化。
比如戰爭新聞,分為敘利亞的、阿富汗的等。
這樣不就ok了呀。
這樣的確可以哈,消費者和生產者。
但是呢,擴充套件性很差,需要很多個topic,每增加一個都需要增加一個topic,無論是對於code 還是 對於業務都困難。
那麼能不能合成一個topic呢?
不知道有沒有看過actionblock 或者channel 這種非同步方式,這種管道模式就是一個入口,處理管道。
這裡設定多跟管道,kafka裡面叫做分割槽。
然後每個分割槽裡面只能被一個消費者消費,這是為了保證record的順序,前文已經提及到了。
然後考慮下一個問題,這裡是一個消費者對於一個分割槽。 且一個分割槽只能被一個消費者裡面的一個分割槽消費。
這樣設計依然存在瑕疵。
有多個消費組,有些消費組需要的record 很多,有些只是取其中很少部分。舉個例子,比如說戰爭新聞,有些消費組只關係俄烏關係,其餘訊息不做處理,進行過濾。
那麼這個消費組消費的就很快,那麼這個消費組裡面就不需要這麼多的消費者。所以肯定不能設計成一對一的關係。
那有沒有可能設計一個消費組裡面的一個消費者消費多個分割槽呢? 這也是可以的。這個時候就有處理一個消費組裡面的消費者要覆蓋這個topic全部分割槽的情況。那麼就要考慮如果增加了一個消費者如何處理,如果一個消費組下線(無論是掉線還是業務需求)如何處理。
至此差不多就是kafka的基本雛形。如果沒有接觸非同步程式設計,那麼的確很難想到kafka這種模型,如果知道actionblock 或者channel 這種,但是更能理解了。
結
至此,簡單分析了一個kafka的分發模型,下一節kafka是如何設計高可用的。以上只是個人理解,如有錯誤,望請指出。