kafka 消息隊列

kafka是使用Java和Scala編寫的一個快速可擴展的高吞吐量的分佈式消息隊列系統。

kafka將數據持久化存儲到磁盤上,自帶分區和副本機制,因而具有較好的持久化保證。

但是kafka的消息消費沒有確認機制,可能因爲consumer崩潰導致消息沒有完成處理。因此不建議將kafka用於一致性較高的業務場景,kafka經常被用做日誌收集和數據倉庫之間的緩存。

比如將網站的瀏覽日誌緩存到kafka,然後從kafka中取出批量寫入ElasticSearch, Hive或者HBase等數據倉庫中。這樣做可以極大的減輕離線分析系統的負載。

架構簡介

kafka架構中有下列角色參與:

  • broker: kafka 集羣中的服務器實例稱爲broker
  • producer: 向broker發送消息的客戶端
  • consumer: 向從borker中讀取消息的客戶端
  • zookeeper: 存儲集羣狀態的註冊中心,不處理具體消息。在負載均衡和集羣擴展等功能中有重要作用。

接下來介紹kafka的邏輯模型:

  • message: 消息是kafka通信的基本單元
  • topic: topic 在邏輯結構上類似於隊列, 每條消息都屬於一個 topic。
  • consumer group: 每個group中可以包含若干 consumer 實例,每個topic可以被多個consumer group 訂閱。
    消費者組擁有唯一的 GroupID 進行標識, 每個 consumer 實例有且只有一個 GroupID。
  • partition: topic 被分爲若干個 partition 進行存儲,每條消息都屬於一個 partition。
  • offset: 每條消息在 partition 中使用 offset (偏移量)作爲唯一標識。

kafka 保證訂閱某個 topic 的所有 consumer group 都會收到該 topic 中所有消息。

topic 中的一條消息在一個 consumer group 中都會被一個 consumer 讀取,且僅會被該 consumer 讀取。

若每個 consumer 都屬於一個獨立的 consumer group 那麼消息會被所有 consumer 讀取,即實現了消息廣播。 若所有 consumer 屬於同一個 consumer group, 那麼消息只會被一個 consumer 讀取,即實現消息單播。

kafka 不會主動將消息推送給消費者, 消費者需要主動從broker中讀取數據。

kafka 沒有消息確認機制,由 consumer 自行控制消費的消息。

partition與消息傳遞的實現

kafka 將一個 topic 中的數據存存儲到多個 partition 中,每個 partition 分爲多個段文件存儲在 broker 節點上。

producer 會與 topic 下所有 partition 保持通信,並根據配置的算法(key-hash 或 round robin等)決定將消息寫入哪個 partition 中。

partition 內部是有序的,但是同一個 topic 的多個 partition 之間不保證有序, 即 topic 不是整體有序的。

kafka 會爲監聽 topic 的 consumer 分配一個 partition。 在一個消費者組內,一個 partition 最多分配給一個 consumer。

當組內 consumer 數量大於 partition 數量時,可能有 consumer 分配不到數據。

一個 partition 可以被屬於不同 group 的多個 consumer 監聽。

consumer 監聽不同 partition 的機制實現了消息只能被組內一個 consumer 消費的特性,避免使用鎖機制極大提高了吞吐率簡化了 broker 實現。

消費者通過 offset 標記自己讀取的位置,主動讀取 parttion 中的數據

消費者向 broker 發送包含 offset 和 max 參數的 fetch 請求來讀取 partition中的數據。 因此,消費者可以自由設置 offset 來控制讀取的位置,從而實現增量讀取或從頭讀取等功能。

當消費者訂閱某個 topic 時,kafka 會將最新的offset告知消費者。

消費者可以將自己當前的 offset 反饋給 kafka, kafka 會將狀態保存到 zookeeper,使得消費者可以自由退出或者重新加入繼續消費。

kafka 沒有消息確認機制,完全由 consumer 設置 offset 來進行消費。因此,kafka broker 不需要維護消息狀態,有利於提高吞吐率。

與很多消息隊列系統不同的是, kafka 不會刪除已消費的信息, 而是根據配置的超時時間或者文件大小限制,刪除較早發送的消息或過大的partition文件。

replica

kafka 在0.8之後版本中支持了副本機制, 每個 topic 分爲多個 partition, 每個 partition 存在多個 replica。

這些 replica 分佈於不同的 broker 節點上, 降低單個 broker 宕機對系統可用性的影響。

kafka 的副本分佈策略是: 在擁有 n 個 broker 節點的集羣中, 將第 i 個 partition 的第 j 個 replica 存儲在第 (i + j) % n 個 broker 上。

同一個 partition 的 replica 中存在一個 leader,生產者消費者只與 leader replica 進行交互, 其它 replica 從leader中同步數據。

kafka提供了兩種主從複製機制:

  • 同步複製:消息被 partition 的所有 alive 狀態 replica 複製消息纔會成功提交,這種方式保證一致性卻極大影響吞吐率。
  • 異步提交:消息被 partition 的 leader replica 寫入即提交成功, 其它 replica 會異步同步數據。這種方式吞吐率較高但一致性較低,leader 崩潰可能導致消息丟失。

kafka通過兩種機制判斷alive狀態:

  • zookeeper的心跳機制:broker必須維護zookeeper的session
  • slave 副本從 leader 複製數據的延遲不能超過閾值。

體驗kafka

安裝kafka

這裏作者選擇用homebrew進行安裝.

brew install kafka

配置文件在/usr/local/etc/kafka/server.properties/usr/local/etc/kafka/zookeeper.properties

啓動zookeeper:

zookeeper-server-start /usr/local/etc/kafka/zookeeper.properties &

啓動kafka:

kafka-server-start /usr/local/etc/kafka/server.properties &

命令行工具

創建topic:

kafka-topics --zookeeper localhost:2181 --create --topic test --partitions 30  --replication-factor 2 
  • zookeeper: 集羣依賴的zookeeper服務地址
  • topic: topic 名稱
  • partitions: topic 的 partition 數
  • replication-factor: 每個 partition 的副本數

查看 topic 信息:

kafka-topics --zookeeper localhost:2181 --describe --topic test

刪除 topic:

kafka-topics --zookeeper localhost:2181 --delete --topic test

查看所有 topic:

kafka-topics --zookeeper localhost:2181 --list

發送消息:

kafka-console-producer --broker-list localhost:9092 --topic test

接收新消息:

kafka-console-consumer --zookeeper localhost:2181 --topic test

從頭讀取消息:

kafka-console-consumer --zookeeper localhost:2181 --topic test --from-beginning
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章