今天咱們來聊聊 Kafka ,主要是帶你從新認識一下 Kafka,聊一下 Kafka 中比較重要的概念和問題。在後面的文章中我會介紹:git
咱們如今常常提到 Kafka 的時候就已經默認它是一個很是優秀的消息隊列了,咱們也會常常拿它給 RocketMQ、RabbitMQ 對比。我以爲 Kafka 相比其餘消息隊列主要的優點以下:數據庫
實際上在早期的時候 Kafka 並非一個合格的消息隊列,早期的 Kafka 在消息隊列領域就像是一個衣衫襤褸的孩子同樣,功能不完備而且有一些小問題好比丟失消息、不保證消息可靠性等等。固然,這也和 LinkedIn 最先開發 Kafka 用於處理海量的日誌有很大關係,哈哈哈,人家原本最開始就不是爲了做爲消息隊列滴,誰知道後面誤打誤撞在消息隊列領域佔據了一席之地。
隨着後續的發展,這些短板都被 Kafka 逐步修復完善。因此,Kafka 做爲消息隊列不可靠這個說法已通過時!安全
先來看一下官網對其的介紹,應該是最權威和實時的了。是英文也沒有關係,我已經將比較重要的信息都爲你提取出來了。服務器
從官方介紹中咱們能夠獲得如下信息:
Kafka 是一個分佈式流式處理平臺。這究竟是什麼意思呢?
流平臺具備三個關鍵功能:架構
Kafka 主要有兩大應用場景:併發
關於 Kafka 幾個很是重要的概念:負載均衡
題外話:早期的 JMS 和 AMQP 屬於消息服務領域權威組織所作的相關的標準,我在 JavaGuide的 《消息隊列其實很簡單》這篇文章中介紹過。可是,這些標準的進化跟不上消息隊列的演進速度,這些標準實際上已經屬於廢棄狀態。因此,可能存在的狀況是:不一樣的消息隊列都有本身的一套消息模型。異步
使用隊列(Queue)做爲消息通訊載體,知足生產者與消費者模式,一條消息只能被一個消費者使用,未被消費的消息在隊列中保留直到被消費或超時。 好比:咱們生產者發送 100 條消息的話,兩個消費者來消費通常狀況下兩個消費者會按照消息發送的順序各自消費一半(也就是你一個我一個的消費。)
隊列模型存在的問題:
假如咱們存在這樣一種狀況:咱們須要將生產者產生的消息分發給多個消費者,而且每一個消費者都能接收到完成的消息內容。
這種狀況,隊列模型就很差解決了。不少比較槓精的人就說:咱們能夠爲每一個消費者建立一個單獨的隊列,讓生產者發送多份。這是一種很是愚蠢的作法,浪費資源不說,還違背了使用消息隊列的目的。分佈式
發佈-訂閱模型主要是爲了解決隊列模型存在的問題。
發佈訂閱模型(Pub-Sub) 使用主題(Topic) 做爲消息通訊載體,相似於廣播模式;發佈者發佈一條消息,該消息經過主題傳遞給全部的訂閱者,在一條消息廣播以後才訂閱的用戶則是收不到該條消息的。
在發佈 - 訂閱模型中,若是隻有一個訂閱者,那它和隊列模型就基本是同樣的了。因此說,發佈 - 訂閱模型在功能層面上是能夠兼容隊列模型的。
Kafka 採用的就是發佈 - 訂閱模型。
RocketMQ 的消息模型和 Kafka 基本是徹底同樣的。惟一的區別是 RocketMQ 中沒有隊列這個概念,與之對應的是 Partition(分區)。ide
Kafka 將生產者發佈的消息發送到 Topic(主題) 中,須要這些消息的消費者能夠訂閱這些 Topic(主題),以下圖所示:
Kafka Topic Partition
上面這張圖也爲咱們引出了,Kafka 比較重要的幾個概念:
同時,你必定也注意到每一個 Broker 中又包含了 Topic 以及 Partition 這兩個重要的概念:
劃重點:Kafka 中的 Partition(分區) 實際上能夠對應成爲消息隊列中的隊列。這樣是否是更好理解一點?
另外,還有一點我以爲比較重要的是 Kafka 爲分區(Partition)引入了多副本(Replica)機制。分區(Partition)中的多個副本之間會有一個叫作 leader 的傢伙,其餘副本稱爲 follower。咱們發送的消息會被髮送到 leader 副本,而後 follower 副本才能從 leader 副本中拉取消息進行同步。
生產者和消費者只與 leader 副本交互。你能夠理解爲其餘副本只是 leader 副本的拷貝,它們的存在只是爲了保證消息存儲的安全性。當 leader 副本發生故障時會從 follower 中選舉出一個 leader,可是 follower 中若是有和 leader 同步程度達不到要求的參加不了 leader 的競選。
Kafka 的多分區(Partition)以及多副本(Replica)機制有什麼好處呢?
要想搞懂 ZooKeeper 在 Kafka 中的做用 必定要本身搭建一個 Kafka 環境而後本身進 ZooKeeper 去看一下有哪些文件夾和 Kafka 有關,每一個節點又保存了什麼信息。 必定不要光看不實踐,這樣學來的也終會忘記!
後面的文章中會介紹如何搭建 Kafka 環境,你且不要急,看了後續文章 3 分鐘就能搭建一個 Kafka 環境。
這部份內容參考和借鑑了這篇文章:https://www.jianshu.com/p/a036405f989c
下圖就是個人本地 Zookeeper ,它成功和我本地的 Kafka 關聯上(如下文件夾結構藉助 idea 插件 ZooKeeper tool 實現)。
ZooKeeper 主要爲 Kafka 提供元數據的管理的功能。
從圖中咱們能夠看出,Zookeeper 主要爲 Kafka 作了下面這些事情:
咱們在使用消息隊列的過程當中常常有業務場景須要嚴格保證消息的消費順序,好比咱們同時發了 2 個消息,這 2 個消息對應的操做分別對應的數據庫操做是:更改用戶會員等級、根據會員等級計算訂單價格。假如這兩條消息的消費順序不同形成的最終結果就會大相徑庭。
咱們知道 Kafka 中 Partition(分區)是真正保存消息的地方,咱們發送的消息都被放在了這裏。而咱們的 Partition(分區)又存在於 Topic(主題)這個概念中,而且咱們能夠給特定 Topic 指定多個 Partition。
Kafka Topic Partitions Layout
每次添加消息到 Partition(分區)的時候都會採用尾加法,如上圖所示。Kafka 只能爲咱們保證 Partition(分區)中的消息有序,而不能保證 Topic(主題)中的 Partition(分區)的有序。
消息在被追加到 Partition(分區)的時候都會分配一個特定的偏移量(offset)。Kafka 經過偏移量(offset)來保證消息在分區內的順序性。
因此,咱們就有一種很簡單的保證消息消費順序的方法:1 個 Topic 只對應一個 Partition。這樣固然能夠解決問題,可是破壞了 Kafka 的設計初衷。
Kafka 中發送 1 條消息的時候,能夠指定 Topic,Partition,Key,Data(數據) 4 個參數。若是你發送消息的時候指定了 Partition 的話,全部消息都會被髮送到指定的 Partition。而且,同一個 key 的消息能夠保證只發送到同一個 partition,這個咱們能夠採用表/對象的 id 來做爲 key 。
總結一下,對於如何保證 Kafka 中消息消費的順序,有了下面兩種方法:
固然不只僅只有上面兩種方法,上面兩種方法是我以爲比較好理解的,
最後給你們一套Kafka的學習資料。內容從最基礎的架構直接講到高級源碼
消費者
深刻服務端
高級應用
Kafka與Spark的集成
相應的文章已經整理造成文檔,git掃碼獲取資料看這裏