分布式消息系統:Kafka
Kafka 是分布式發布-訂閱消息系統。它最初由 LinkedIn 公司開發,之后成為 Apache 項目的一部分。Kafka 是一個分布式的,可劃分的,冗余備份的持久性的日志服務。它主要用于處理活躍的流式數據。
在大數據系統中,常常會碰到一個問題,整個大數據是由各個子系統組成,數據需要在各個子系統中高性能,低延遲的不停流轉。傳統的企業消息系統并 不是非常適合大規模的數據處理。為了已在同時搞定在線應用(消息)和離線應用(數據文件,日志)Kafka 就出現了。Kafka 可以起到兩個作用:
- 降低系統組網復雜度。
- 降低編程復雜度,各個子系統不在是相互協商接口,各個子系統類似插口插在插座上,Kafka 承擔高速數據總線的作用。
Kafka 主要特點:
- 同時為發布和訂閱提供高吞吐量。據了解,Kafka 每秒可以生產約 25 萬消息(50 MB),每秒處理 55 萬消息(110 MB)。
- 可進行持久化操作。將消息持久化到磁盤,因此可用于批量消費,例如 ETL,以及實時應用程序。通過將數據持久化到硬盤以及 replication 防止數據丟失。
- 分布式系統,易于向外擴展。所有的 producer、broker 和 consumer 都會有多個,均為分布式的。無需停機即可擴展機器。
- 消息被處理的狀態是在 consumer 端維護,而不是由 server 端維護。當失敗時能自動平衡。
- 支持 online 和 offline 的場景。
Kayka 的架構:
Kayka 的整體架構非常簡單,是顯式分布式架構,producer、broker(kafka)和 consumer 都可以有多個。Producer,consumer 實現 Kafka 注冊的接口,數據從 producer 發送到 broker,broker 承擔一個中間緩存和分發的作用。broker 分發注冊到系統中的 consumer。broker 的作用類似于緩存,即活躍的數據和離線處理系統之間的緩存。客戶端和服務器端的通信,是基于簡單,高性能,且與編程語言無關的 TCP 協議。幾個基本概念:
- Topic:特指 Kafka 處理的消息源(feeds of messages)的不同分類。
- Partition:Topic 物理上的分組,一個 topic 可以分為多個 partition,每個 partition 是一個有序的隊列。partition 中的每條消息都會被分配一個有序的 id(offset)。
- Message:消息,是通信的基本單位,每個 producer 可以向一個 topic(主題)發布一些消息。
- Producers:消息和數據生產者,向 Kafka 的一個 topic 發布消息的過程叫做 producers。
- Consumers:消息和數據消費者,訂閱 topics 并處理其發布的消息的過程叫做 consumers。
- Broker:緩存代理,Kafa 集群中的一臺或多臺服務器統稱為 broker。
消息發送的流程:
- Producer 根據指定的 partition 方法(round-robin、hash 等),將消息發布到指定 topic 的 partition 里面
- kafka 集群接收到 Producer 發過來的消息后,將其持久化到硬盤,并保留消息指定時長(可配置),而不關注消息是否被消費。
- Consumer 從 kafka 集群 pull 數據,并控制獲取消息的 offset
Kayka 的設計:
1、吞吐量
高吞吐是 kafka 需要實現的核心目標之一,為此 kafka 做了以下一些設計:
- 數據磁盤持久化:消息不在內存中 cache,直接寫入到磁盤,充分利用磁盤的順序讀寫性能
- zero-copy:減少 IO 操作步驟
- 數據批量發送
- 數據壓縮
- Topic 劃分為多個 partition,提高 parallelism
負載均衡
- producer 根據用戶指定的算法,將消息發送到指定的 partition
- 存在多個 partiiton,每個 partition 有自己的 replica,每個 replica 分布在不同的 Broker 節點上
- 多個 partition 需要選取出 lead partition,lead partition 負責讀寫,并由 zookeeper 負責 fail over
- 通過 zookeeper 管理 broker 與 consumer 的動態加入與離開
拉取系統
由于 kafka broker 會持久化數據,broker 沒有內存壓力,因此,consumer 非常適合采取 pull 的方式消費數據,具有以下幾點好處:
- 簡化 kafka 設計
- consumer 根據消費能力自主控制消息拉取速度
- consumer 根據自身情況自主選擇消費模式,例如批量,重復消費,從尾端開始消費等
可擴展性
當需要增加 broker 結點時,新增的 broker 會向 zookeeper 注冊,而 producer 及 consumer 會根據注冊在 zookeeper 上的 watcher 感知這些變化,并及時作出調整。
Kayka 的應用場景:
1. 消息隊列
比起大多數的消息系統來說,Kafka 有更好的吞吐量,內置的分區,冗余及容錯性,這讓 Kafka 成為了一個很好的大規模消息處理應用的解決方案。消息系統一般吞吐量相對較低,但是需要更小的端到端延時,并嘗嘗依賴于 Kafka 提供的強大的持久性保障。在這個領域,Kafka 足以媲美傳統消息系統,如 ActiveMR 或 RabbitMQ。
2. 行為跟蹤
Kafka 的另一個應用場景是跟蹤用戶瀏覽頁面、搜索及其他行為,以發布-訂閱的模式實時記錄到對應的 topic 里。那么這些結果被訂閱者拿到后,就可以做進一步的實時處理,或實時監控,或放到 hadoop/離線數據倉庫里處理。
3. 元信息監控
作為操作記錄的監控模塊來使用,即匯集記錄一些操作信息,可以理解為運維性質的數據監控吧。
4. 日志收集
日志收集方面,其實開源產品有很多,包括 Scribe、Apache Flume。很多人使用 Kafka 代替日志聚合(log aggregation)。日志聚合一般來說是從服務器上收集日志文件,然后放到一個集中的位置(文件服務器或 HDFS)進行處理。然而 Kafka 忽略掉文件的細節,將其更清晰地抽象成一個個日志或事件的消息流。這就讓 Kafka 處理過程延遲更低,更容易支持多數據源和分布式數據處理。比起以日志為中心的系統比如 Scribe 或者 Flume 來說,Kafka 提供同樣高效的性能和因為復制導致的更高的耐用性保證,以及更低的端到端延遲。
5. 流處理
這個場景可能比較多,也很好理解。保存收集流數據,以提供之后對接的 Storm 或其他流式計算框架進行處理。很多用戶會將那些從原始 topic 來的數據進行階段性處理,匯總,擴充或者以其他的方式轉換到新的 topic 下再繼續后面的處理。例如一個文章推薦的處理流程,可能是先從 RSS 數據源中抓取文章的內容,然后將其丟入一個叫做“文章”的 topic 中;后續操作可能是需要對這個內容進行清理,比如回復正常數據或者刪除重復數據,最后再將內容匹配的結果返還給用戶。這就在一個獨立的 topic 之外,產生了一系列的實時數據處理的流程。Strom 和 Samza 是非常著名的實現這種類型數據轉換的框架。
6. 事件源
事件源是一種應用程序設計的方式,該方式的狀態轉移被記錄為按時間順序排序的記錄序列。Kafka 可以存儲大量的日志數據,這使得它成為一個對這種方式的應用來說絕佳的后臺。比如動態匯總(News feed)。
7. 持久性日志(commit log)
Kafka 可以為一種外部的持久性日志的分布式系統提供服務。這種日志可以在節點間備份數據,并為故障節點數據回復提供一種重新同步的機制。Kafka 中日志壓縮功能為這種用法提供了條件。在這種用法中,Kafka 類似于 Apache BookKeeper 項目。
Kayka 的設計要點:
1、直接使用 linux 文件系統的 cache,來高效緩存數據。
2、采用 linux Zero-Copy 提高發送性能。傳統的數據發送需要發送 4 次上下文切換,采用 sendfile 系統調用之后,數據直接在內核態交換,系統上下文切換減少為 2 次。根據測試結果,可以提高 60% 的數據發送性能。Zero-Copy 詳細的技術細節可以參考:https://www.ibm.com/developerworks/linux/library/j-zerocopy/
3、數據在磁盤上存取代價為O(1)。kafka 以 topic 來進行消息管理,每個 topic 包含多個 part(ition),每個 part 對應一個邏輯 log,有多個 segment 組成。每個 segment 中存儲多條消息(見下圖),消息 id 由其邏輯位置決定,即從消息 id 可直接定位到消息的存儲位置,避免 id 到位置的額外映射。每個 part 在內存中對應一個 index,記錄每個 segment 中的第一條消息偏移。發布者發到某個 topic 的消息會被均勻的分布到多個 part 上(隨機或根據用戶指定的回調函數進行分布),broker 收到發布消息往對應 part 的最后一個 segment 上添加該消息,當某個 segment 上的消息條數達到配置值或消息發布時間超過閾值時,segment 上的消息會被 flush 到磁盤,只有 flush 到磁盤上的消息訂閱者才能訂閱到,segment 達到一定的大小后將不會再往該 segment 寫數據,broker 會創建新的 segment。
4、顯式分布式,即所有的 producer、broker 和 consumer 都會有多個,均為分布式的。Producer 和 broker 之間沒有負載均衡機制。broker 和 consumer 之間利用 zookeeper 進行負載均衡。所有 broker 和 consumer 都會在 zookeeper 中進行注冊,且 zookeeper 會保存他們的一些元數據信息。如果某個 broker 和 consumer 發生了變化,所有其他的 broker 和 consumer 都會得到通知。
參考資料:
<span id="shareA4" class="fl">
</span>