Kafka訊息系統基礎知識索引

小姐姐味道發表於2018-12-18

我們在《360度測試:KAFKA會丟資料麼?其高可用是否滿足需求?》這篇文章中,詳細說明了KAFKA是否適合用在業務系統中。但有些朋友,還不知道KAFKA為何物,以及它為何存在。這在工作和麵試中是比較吃虧的,因為不知道什麼時候起,KAFKA似乎成了一種工程師的必備技能。

一些觀念的修正

從 0.9 版本開始,Kafka 的標語已經從“一個高吞吐量,分散式的訊息系統”改為"一個分散式流平臺"。

Kafka不僅僅是一個佇列,而且是一個儲存,有超強的堆積能力。

Kafka不僅用在吞吐量高的大資料場景,也可以用在有事務要求的業務系統上,但效能較低。

Kafka不是Topic越多越好,由於其設計原理,在數量達到閾值後,其效能和Topic數量成反比。

引入了訊息佇列,就等於引入了非同步,不管你是出於什麼目的。這通常意味著業務流程的改變,甚至產品體驗的變更。

訊息系統是什麼

典型場景

Kafka訊息系統基礎知識索引
上圖是一些小系統的典型架構。考慮訂單的業務場景,有大量的請求指向我們的業務系統,如果直接經過複雜的業務邏輯進入業務表,將會有大量請求超時失敗。所以我們加入了一張中間緩衝表(或者Redis),用來承接使用者的請求。然後,有一個定時任務,不斷的從緩衝表中獲取資料,進行真正的業務邏輯處理。

這種設計有以下幾個問題:

  • 定時任務的輪詢間隔不好控制。業務處理容易延遲。

  • 無法橫向擴容處理能力,且會引入分散式鎖、順序性保證等問題。

  • 當其他業務也需要這些訂單資料的時候,業務邏輯就必須要加入到定時任務裡。

當訪問量增加、業務邏輯複雜化的時候,訊息佇列就呼之欲出了。

Kafka訊息系統基礎知識索引
請求會暫存在訊息佇列,然後實時通過推(或者拉)的方式進行處理。 在此場景下,訊息佇列充當了削峰和冗餘的元件。

訊息系統的作用

削峰 用於承接超出業務系統處理能力的請求,使業務平穩執行。這能夠大量節約成本,比如某些秒殺活動,並不是針對峰值設計容量。

緩衝 在服務層和緩慢的落地層作為緩衝層存在,作用與削峰類似,但主要用於服務內資料流轉。比如批量簡訊傳送。

解耦 專案尹始,並不能確定具體需求。訊息佇列可以作為一個介面層,解耦重要的業務流程。只需要遵守約定,針對資料程式設計即可獲取擴充套件能力。

冗餘 訊息資料能夠採用一對多的方式,供多個毫無關聯的業務使用。

健壯性 訊息佇列可以堆積請求,所以消費端業務即使短時間死掉,也不會影響主要業務的正常進行。

訊息系統要求

訊息系統即然這麼重要,那麼除了能夠保證高可用,對它本身的特性也有較高需求。大體有下面幾點:

效能要高 包含訊息投遞和訊息消費,都要快。一般通過增加分片數獲取並行處理能力。

訊息要可靠 在某些場景,不能丟訊息。生產、消費、MQ端都不能丟訊息。一般通過增加副本,強制刷盤來解決。

擴充套件性要好 能夠陪你把專案做大,陪你到天荒地老。增加節點叢集增大後,不能降低效能。

生態成熟 監控、運維、多語言支援、社群的活躍。

KAFKA名詞解釋

基本功能

Kafka是一個分散式訊息(儲存)系統。分散式系統通過分片增加並行度;通過副本增加可靠性,kafka也不例外。我們來看一下它的結構,順便解釋一下其中的術語。

Kafka訊息系統基礎知識索引
你在一臺機器上安裝了Kafka,那麼這臺機器就叫Broker,KAFKA叢集包含了一個或者多個這樣的例項。

負責往KAFKA寫入資料的元件就叫做Producer,訊息的生產者一般寫在業務系統裡。

傳送到KAFKA的訊息可能有多種,如何區別其分類?就是Topic的概念。一個主題分散式化後,可能會存在多個Broker上。

將Topic拆成多個段,增加並行度後,拆成的每個部分叫做Partition,分割槽一般平均分佈在所有機器上。

那些消費Kafka中資料的應用程式,就叫做Consumer,我們給某個主題的某個消費業務起一個名字,這麼名字就叫做Consumer Group

擴充套件功能

Connector 聯結器Task,包含Source和Sink兩種介面,給使用者提供了自定義資料流轉的可能。比如從JDBC匯入到Kafka,或者將Kafka資料直接落地到DB。

Stream 類似於Spark Stream,能夠進行流資料處理。但它本身沒有叢集,只是在KAFKA叢集上的抽象。如果你想要實時的流處理,且不需要Hadoop生態的某些東西,那麼這個比較適合你。

Topic

Kafka訊息系統基礎知識索引

我們的訊息就是寫在主題裡。有了多個Topic,就可以對訊息進行歸類與隔離。比如登入資訊寫在user_activity_topic,日誌訊息寫在log_topic中。

每一個topic都可以調整其分割槽數量。假設我們的叢集有三個Broker,那麼當分割槽數量為1的時候,訊息就僅寫在其中一個節點上;當我們的分割槽為3,訊息會根據hash寫到三個節點上;當我們的分割槽為6,那每個節點將會有2個分割槽資訊。增加分割槽可以增加並行度,但不是越多越好。一般,6-12最佳,最好能夠被節點數整除,避免資料傾斜。

每個分割槽都由一系列有序的、不可變的訊息組成,這些訊息被順序的追加。分割槽中的每個訊息都有一個連續的序列號叫做offset。Kafka將保留配置時間內的所有訊息,所以它也是一個臨時儲存。在這段時間內,所有的訊息都可被消費,並且可以通過改變offset的值進行重複、多次消費。

Offset一般由消費者管理,當然也可以通過程式按需要設定。Offset只有commit以後,才會改變,否則,你將一直獲取重複的資料。新的kafka已經將這些Offset的放到了一個專有的主題:__consumer_offsets,就是上圖的紫色區域。

值得一提的是,消費者的個數,不要超過分割槽的個數。否則,多出來的消費者,將接收不到任何資料。

ISR

分散式系統保證資料可靠性的一個常用手段就是增加副本個數,ISR就是建立在這個手段上。

ISR全稱"In-Sync Replicas",是保證HA和一致性的重要機制。副本數對Kafka的吞吐率是有一定的影響,但極大的增強了可用性。一般2-3個為宜。

副本有兩個要素,一個是數量要夠多,一個是不要落在同一個例項上。ISR是針對與Partition的,每個分割槽都有一個同步列表。N個replicas中,其中一個replica為leader,其他都為follower, leader處理partition的所有讀寫請求,其他的都是備份。與此同時,follower會被動定期地去複製leader上的資料。

如果一個flower比一個leader落後太多,或者超過一定時間未發起資料複製請求,則leader將其重ISR中移除。

當ISR中所有Replica都向Leader傳送ACK時,leader才commit。

Kafka的ISR的管理最終都會反饋到Zookeeper節點上。具體位置為:/brokers/topics/[topic]/partitions/[partition]/state。當Leader節點失效,也會依賴Zk進行新的Leader選舉。Offset轉移到Kafka內部的Topic以後,KAFKA對ZK的依賴就越來越小了。

可靠性

訊息投遞語義

At least once 可能會丟訊息,但不不會重複

At most once 不不丟訊息,但可能重複,所以消費端要做冪等

Exactly once 訊息不不會丟,且保證只投遞⼀一次

整體的訊息投遞語義需要Producer端和Consumer端兩者來保證。KAFKA預設是At most once,也可以通過配置事務達到Exactly once,但效率很低,不推薦。

ACK

當生產者向leader傳送資料時,可以通過request.required.acks引數來設定資料可靠性的級別:

1(預設) 資料傳送到Kafka後,經過leader成功接收訊息的的確認,就算是傳送成功了。在這種情況下,如果leader當機了,則會丟失資料。

0 生產者將資料傳送出去就不管了,不去等待任何返回。這種情況下資料傳輸效率最高,但是資料可靠性確是最低的。

-1 producer需要等待ISR中的所有follower都確認接收到資料後才算一次傳送完成,可靠性最高。

Kafka訊息系統基礎知識索引

KAFKA為什麼快

Cache Filesystem Cache PageCache快取

順序寫 由於現代的作業系統提供了預讀和寫技術,磁碟的順序寫大多數情況下比隨機寫記憶體還要快。

Zero-copy 零拷⻉,少了一次記憶體交換。

Batching of Messages 批量量處理。合併小的請求,然後以流的方式進行互動,直頂網路上限。

Pull 拉模式 使用拉模式進行訊息的獲取消費,與消費端處理能力相符。

使用場景

  • 傳遞業務訊息

  • 使用者活動日誌 • 監控項等

  • 日誌

  • 流處理,比如某些聚合

  • Commit Log,作為某些重要業務的冗餘

下面是一個日誌方面的典型使用場景。

Kafka訊息系統基礎知識索引

壓測

KAFKA自帶壓測工具,如下。

./kafka-producer-perf-test.sh --topic test001 --num- records 1000000 --record-size 1024 --throughput -1 --producer.config ../config/producer.properties
複製程式碼

配置管理

關注點

應⽤用場景 不同的應用場景有不一樣的配置策略和不一樣的SLA服務水準。需要搞清楚自己的訊息是否允許丟失或者重複,然後設定相應的副本數量和ACK模式。

Lag 要時刻注意訊息的積壓。Lag太高意味著處理能力有問題。如果在低峰時候你的訊息有積壓,那麼當大流量到來,必然會出問題。

擴容 擴容後會涉及到partition的重新分佈,你的網路頻寬可能會是瓶頸。

磁碟滿了 建議設定過期天數,或者設定磁碟最大使用量。

log.retention.bytes
複製程式碼

過期刪除 磁碟空間是有限的,建議保留最近的記錄,其餘自動刪除。

log.retention.hours	
log.retention.minutes	
log.retention.ms	
複製程式碼

監控管理工具

KafkaManager 雅虎出品,可管理多個Kafka叢集,是目前功能最全的管理工具。但是注意,當你的Topic太多,監控資料會佔用你大量的頻寬,造成你的機器負載增高。其監控功能偏弱,不滿足需求。

KafkaOffsetMonitor 程式一個jar包的形式執行,部署較為方便。只有監控功能,使用起來也較為安全。

Kafka Web Console 監控功能較為全面,可以預覽訊息,監控Offset、Lag等資訊,不建議在生產環境中使用。

Burrow 是LinkedIn開源的一款專門監控consumer lag的框架。支援報警,只提供HTTP介面,沒有webui。

Availability Monitor for Kafka 微軟開源的Kafka可用性、延遲性的監控框架,提供JMX介面,用的很少。

Rebalance

消費端Rebalance

消費端的上線下線會造成分割槽與消費者的關係重新分配,造成Rebalance。業務會發生超時、抖動等。

服務端reassign

伺服器擴容、縮容,節點啟動、關閉,會造成資料的傾斜,需要對partition進行reassign。在kafka manager後臺可以手動觸發這個過程,使得分割槽的分佈更加平均。

這個過程會造成叢集間大量的資料拷貝,當你的叢集資料量大,這個過程會持續數個小時或者幾天,謹慎操作。

linkedin開源了其自動化管理工具cruise-control,有自動化運維需求的不妨一看。

結尾

本文是KAFKA相關的最基礎的知識,基本涵蓋了大部分簡單的面試題。

為了達到Exactly once這個語義,KAFKA做了很多努力,努力的結果就是幾乎不可用,吞吐量實在是太低了。如果你真要將“高可靠”掛在嘴上,不如做好“補償策略”。效能不成,最終的結果可能是整體不可用;而資料丟失,僅是極端情況下的一部分小資料而已。你會如何權衡呢?

大流量下的KAFKA是非常嚇人的,資料經常將網路卡打滿。而一旦Broker當機,如果單節點有上T的資料,光啟動就需要半個小時,它還要作為Follower去追趕其他Master分割槽的資料。所以,不要讓你的KAFKA叢集太大,故障恢復會是一場災難。啟動以後,如果執行reassign,又會是另一番折騰了。

Kafka訊息系統基礎知識索引

相關文章