Kafka 官網(wǎng):
http://kafka.apache.org/
Kafka 主要設計目標如下:
以時間復雜度為 O(1) 的方式提供消息持久化能力,即使對 TB 級以上數(shù)據(jù)也能保證常數(shù)時間的訪問性能。
高吞吐率氮趋。即使在非常廉價的商用機器上也能做到單機支持每秒 100K 條消息的傳輸。
支持 Kafka Server 間的消息分區(qū),及分布式消費枣氧,同時保證每個 Partition 內(nèi)的消息順序傳輸。
同時支持離線數(shù)據(jù)處理和實時數(shù)據(jù)處理垮刹。
支持在線水平擴展达吞。
Kafka 通常用于兩大類應用程序:
建立實時流數(shù)據(jù)管道,以可靠地在系統(tǒng)或應用程序之間獲取數(shù)據(jù)危纫。
構建實時流應用程序宗挥,以轉換或響應數(shù)據(jù)流乌庶。
要了解 Kafka 如何執(zhí)行這些操作,讓我們從頭開始深入研究 Kafka 的功能契耿。首先幾個概念:
Kafka 在一個或多個可以跨越多個數(shù)據(jù)中心的服務器上作為集群運行瞒大。
Kafka 集群將記錄流存儲在稱為主題的類別中。
每個記錄由一個鍵搪桂,一個值和一個時間戳組成透敌。
Kafka 架構體系如下圖:
Kafka 的應用場景非常多, 下面我們就來舉幾個我們最常見的場景:
①用戶的活動跟蹤:
用戶在網(wǎng)站的不同活動消息發(fā)布到不同的主題中心,然后可以對這些消息進行實時監(jiān)測踢械、實時處理酗电。
當然,也可以加載到 Hadoop 或離線處理數(shù)據(jù)倉庫内列,對用戶進行畫像撵术。像淘寶、天貓话瞧、京東這些大型電商平臺嫩与,用戶的所有活動都要進行追蹤的。
②日志收集如下圖:
③限流削峰如下圖:
④高吞吐率實現(xiàn):
Kafka 與其他 MQ 相比交排,最大的特點就是高吞吐率划滋。為了增加存儲能力,Kafka 將所有的消息都寫入到了低速大容量的硬盤埃篓。
按理說处坪,這將導致性能損失,但實際上架专,Kafka 仍然可以保持超高的吞吐率同窘,并且其性能并未受到影響。
其主要采用如下方式實現(xiàn)了高吞吐率:
順序讀寫:Kafka 將消息寫入到了分區(qū) Partition 中胶征,而分區(qū)中的消息又是順序讀寫的塞椎。順序讀寫要快于隨機讀寫。
零拷貝:生產(chǎn)者睛低、消費者對于 Kafka 中的消息是采用零拷貝實現(xiàn)的案狠。
批量發(fā)送:Kafka 允許批量發(fā)送模式。
消息壓縮:Kafka 允許對消息集合進行壓縮钱雷。
Kafka的優(yōu)點如下:
①解耦:
在項目啟動之初來預測將來項目會碰到什么需求骂铁,是極其困難的。
消息系統(tǒng)在處理過程中間插入了一個隱含的罩抗、基于數(shù)據(jù)的接口層拉庵,兩邊的處理過程都要實現(xiàn)這一接口。
這允許你獨立的擴展或修改兩邊的處理過程套蒂,只要確保它們遵守同樣的接口約束钞支。
②冗余(副本):
有些情況下茫蛹,處理數(shù)據(jù)的過程會失敗。除非數(shù)據(jù)被持久化烁挟,否則將造成丟失婴洼。
消息隊列把數(shù)據(jù)進行持久化直到它們已經(jīng)被完全處理,通過這一方式規(guī)避了數(shù)據(jù)丟失風險撼嗓。
許多消息隊列所采用的"插入-獲取-刪除"范式中柬采,在把一個消息從隊列中刪除之前,需要你的處理系統(tǒng)明確的指出該消息已經(jīng)被處理完畢且警,從而確保你的數(shù)據(jù)被安全的保存直到你使用完畢粉捻。
③擴展性:
因為消息隊列解耦了你的處理過程,所以增大消息入隊和處理的頻率是很容易的斑芜,只要另外增加處理過程即可肩刃。不需要改變代碼、不需要調(diào)節(jié)參數(shù)押搪。擴展就像調(diào)大電力按鈕一樣簡單树酪。
④靈活性&峰值處理能力:
在訪問量劇增的情況下浅碾,應用仍然需要繼續(xù)發(fā)揮作用大州,但是這樣的突發(fā)流量并不常見;如果為以能處理這類峰值訪問為標準來投入資源隨時待命無疑是巨大的浪費垂谢。
使用消息隊列能夠使關鍵組件頂住突發(fā)的訪問壓力厦画,而不會因為突發(fā)的超負荷的請求而完全崩潰。
⑤可恢復性:
系統(tǒng)的一部分組件失效時滥朱,不會影響到整個系統(tǒng)根暑。消息隊列降低了進程間的耦合度,所以即使一個處理消息的進程掛掉徙邻,加入隊列中的消息仍然可以在系統(tǒng)恢復后被處理排嫌。
⑥順序保證:
在大多使用場景下,數(shù)據(jù)處理的順序都很重要缰犁。大部分消息隊列本來就是排序的淳地,并且能保證數(shù)據(jù)會按照特定的順序來處理。Kafka 保證一個 Partition 內(nèi)的消息的有序性帅容。
⑦緩沖:
在任何重要的系統(tǒng)中颇象,都會有需要不同的處理時間的元素。例如并徘,加載一張圖片比應用過濾器花費更少的時間遣钳。
消息隊列通過一個緩沖層來幫助任務最高效率的執(zhí)行,寫入隊列的處理會盡可能的快速麦乞。該緩沖有助于控制和優(yōu)化數(shù)據(jù)流經(jīng)過系統(tǒng)的速度蕴茴。
⑧異步通信:
很多時候劝评,用戶不想也不需要立即處理消息。消息隊列提供了異步處理機制倦淀,允許用戶把一個消息放入隊列付翁,但并不立即處理它。想向隊列中放入多少消息就放多少晃听,然后在需要的時候再去處理它們百侧。
Kafka 于其他 MQ 對比如下:
①RabbitMQ:
RabbitMQ 是使用 Erlang 編寫的一個開源的消息隊列,本身支持很多的協(xié)議:AMQP能扒,XMPP佣渴,SMTP,STOMP初斑,也正因如此辛润,它非常重量級,更適合于企業(yè)級的開發(fā)见秤。
同時實現(xiàn)了 Broker 構架砂竖,這意味著消息在發(fā)送給客戶端時先在中心隊列排隊。對路由鹃答,負載均衡或者數(shù)據(jù)持久化都有很好的支持乎澄。
②Redis:
Redis 是一個基于 Key-Value 對的 NoSQL 數(shù)據(jù)庫,開發(fā)維護很活躍测摔。
雖然它是一個 Key-Value 數(shù)據(jù)庫存儲系統(tǒng)置济,但它本身支持 MQ 功能,所以完全可以當做一個輕量級的隊列服務來使用锋八。
對于 RabbitMQ 和 Redis 的入隊和出隊操作浙于,各執(zhí)行 100 萬次,每 10 萬次記錄一次執(zhí)行時間挟纱。測試數(shù)據(jù)分為 128Bytes羞酗、512Bytes、1K 和 10K 四個不同大小的數(shù)據(jù)紊服。
實驗表明:入隊時檀轨,當數(shù)據(jù)比較小時 Redis 的性能要高于 RabbitMQ,而如果數(shù)據(jù)大小超過了 10K围苫,Redis 則慢的無法忍受裤园;出隊時,無論數(shù)據(jù)大小剂府,Redis 都表現(xiàn)出非常好的性能拧揽,而 RabbitMQ 的出隊性能則遠低于 Redis。
③ZeroMQ:
ZeroMQ 號稱最快的消息隊列系統(tǒng),尤其針對大吞吐量的需求場景淤袜。
ZeroMQ 能夠實現(xiàn) RabbitMQ 不擅長的高級/復雜的隊列痒谴,但是開發(fā)人員需要自己組合多種技術框架,技術上的復雜度是對這 MQ 能夠應用成功的挑戰(zhàn)铡羡。
ZeroMQ 具有一個獨特的非中間件的模式积蔚,你不需要安裝和運行一個消息服務器或中間件,因為你的應用程序將扮演這個服務器角色烦周。
你只需要簡單的引用 ZeroMQ 程序庫尽爆,可以使用 NuGet 安裝,然后你就可以愉快的在應用程序之間發(fā)送消息了读慎。
但是 ZeroMQ 僅提供非持久性的隊列漱贱,也就是說如果宕機,數(shù)據(jù)將會丟失夭委。其中幅狮,Twitter 的 Storm 0.9.0 以前的版本中默認使用 ZeroMQ 作為數(shù)據(jù)流的傳輸(Storm 從 0.9 版本開始同時支持 ZeroMQ 和 Netty 作為傳輸模塊)。
④ActiveMQ:
ActiveMQ 是 Apache 下的一個子項目株灸。類似于 ZeroMQ崇摄,它能夠以代理人和點對點的技術實現(xiàn)隊列。同時類似于 RabbitMQ慌烧,它少量代碼就可以高效地實現(xiàn)高級應用場景逐抑。
⑤Kafka/Jafka:
Kafka 是 Apache 下的一個子項目,是一個高性能跨語言分布式發(fā)布/訂閱消息隊列系統(tǒng)杏死,而 Jafka 是在 Kafka 之上孵化而來的泵肄,即 Kafka 的一個升級版。
具有以下特性:
快速持久化淑翼,可以在 O(1) 的系統(tǒng)開銷下進行消息持久化。
高吞吐品追,在一臺普通的服務器上既可以達到 10W/s 的吞吐速率玄括。
完全的分布式系統(tǒng),Broker肉瓦、Producer遭京、Consumer 都原生自動支持分布式,自動實現(xiàn)負載均衡泞莉。
支持 Hadoop 數(shù)據(jù)并行加載哪雕,對于像 Hadoop 的一樣的日志數(shù)據(jù)和離線分析系統(tǒng),但又要求實時處理的限制鲫趁,這是一個可行的解決方案斯嚎。
Kafka 通過 Hadoop 的并行加載機制統(tǒng)一了在線和離線的消息處理。Apache Kafka 相對于 ActiveMQ 是一個非常輕量級的消息系統(tǒng),除了性能非常好之外堡僻,還是一個工作良好的分布式系統(tǒng)糠惫。
Kafka的幾種重要角色如下:
①Kafka 作為存儲系統(tǒng):
任何允許發(fā)布與使用無關的消息發(fā)布的消息隊列都有效地充當了運行中消息的存儲系統(tǒng)。Kafka 的不同之處在于它是一個非常好的存儲系統(tǒng)钉疫。
寫入 Kafka 的數(shù)據(jù)將寫入磁盤并進行復制以實現(xiàn)容錯功能硼讽。Kafka 允許生產(chǎn)者等待確認,以便直到完全復制并確保即使寫入服務器失敗的情況下寫入也不會完成牲阁。Kafka 的磁盤結構可以很好地擴展使用-無論服務器上有 50KB 還是 50TB 的持久數(shù)據(jù)固阁,Kafka 都將執(zhí)行相同的操作。由于認真對待存儲并允許客戶端控制其讀取位置城菊,因此您可以將 Kafka 視為一種專用于高性能您炉,低延遲提交日志存儲,復制和傳播的專用分布式文件系統(tǒng)役电。
②Kafka 作為消息傳遞系統(tǒng):
Kafka 的流概念與傳統(tǒng)的企業(yè)消息傳遞系統(tǒng)相比如何赚爵?
傳統(tǒng)上,消息傳遞具有兩種模型:排隊和發(fā)布訂閱法瑟。在隊列中冀膝,一組使用者可以從服務器中讀取內(nèi)容,并且每條記錄都將轉到其中一個霎挟。在發(fā)布-訂閱記錄中廣播給所有消費者窝剖。這兩個模型中的每一個都有優(yōu)點和缺點。排隊的優(yōu)勢在于酥夭,它允許您將數(shù)據(jù)處理劃分到多個使用者實例上赐纱,從而擴展處理量。不幸的是熬北,隊列不是多用戶的—一次進程讀取了丟失的數(shù)據(jù)疙描。發(fā)布-訂閱允許您將數(shù)據(jù)廣播到多個進程,但是由于每條消息都傳遞給每個訂閱者讶隐,因此無法擴展處理起胰。Kafka 的消費者群體概念概括了這兩個概念。與隊列一樣巫延,使用者組允許您將處理劃分為一組進程(使用者組的成員)效五。與發(fā)布訂閱一樣,Kafka 允許您將消息廣播到多個消費者組炉峰。Kafka 模型的優(yōu)點在于畏妖,每個主題都具有這些屬性-可以擴展處理范圍,并且是多訂閱者疼阔,無需選擇其中一個戒劫。與傳統(tǒng)的消息傳遞系統(tǒng)相比半夷,Kafka 還具有更強的訂購保證。傳統(tǒng)隊列將記錄按順序保留在服務器上谱仪,如果多個使用者從隊列中消費玻熙,則服務器將按記錄的存儲順序分發(fā)記錄。但是疯攒,盡管服務器按順序分發(fā)記錄嗦随,但是這些記錄是異步傳遞給使用者的,因此它們可能在不同的使用者上亂序到達敬尺。這實際上意味著在并行使用的情況下會丟失記錄的順序枚尼。消息傳遞系統(tǒng)通常通過“專有使用者”的概念來解決此問題,該概念僅允許一個進程從隊列中使用砂吞,但是署恍,這當然意味著在處理中沒有并行性。Kafka 做得更好蜻直,通過在主題內(nèi)具有并行性(即分區(qū))的概念盯质,Kafka 能夠在用戶進程池中提供排序保證和負載均衡。這是通過將主題中的分區(qū)分配給消費者組中的消費者來實現(xiàn)的概而,以便每個分區(qū)都由組中的一個消費者完全消費呼巷。通過這樣做,我們確保使用者是該分區(qū)的唯一讀取器赎瑰,并按順序使用數(shù)據(jù)王悍。由于存在許多分區(qū),因此仍然可以平衡許多使用者實例上的負載餐曼。但是請注意压储,使用者組中的使用者實例不能超過分區(qū)。
③Kafka 用作流處理:
僅讀取源譬,寫入和存儲數(shù)據(jù)流是不夠的集惋,目的是實現(xiàn)對流的實時處理。
在 Kafka 中瓶佳,流處理器是指從輸入主題中獲取連續(xù)數(shù)據(jù)流芋膘,對該輸入進行一些處理并生成連續(xù)數(shù)據(jù)流以輸出主題的任何東西。例如霸饲,零售應用程序可以接受銷售和裝運的輸入流,并輸出根據(jù)此數(shù)據(jù)計算出的重新訂購和價格調(diào)整流臂拓『衤觯可以直接使用生產(chǎn)者和消費者 API 進行簡單處理。但是胶惰,對于更復雜的轉換傻工,Kafka 提供了完全集成的 Streams API。這允許構建執(zhí)行非重要處理的應用程序,這些應用程序計算流的聚合或將流連接在一起中捆。該功能有助于解決此類應用程序所面臨的難題:處理無序數(shù)據(jù)鸯匹,在代碼更改時重新處理輸入,執(zhí)行狀態(tài)計算等泄伪。流 API 建立在 Kafka 提供的核心原語之上:它使用生產(chǎn)者和使用者 API 進行輸入殴蓬,使用 Kafka 進行狀態(tài)存儲,并使用相同的組機制來實現(xiàn)流處理器實例之間的容錯蟋滴。
Kafka 中的關鍵術語解釋
Topic:主題染厅。
在 Kafka 中,使用一個類別屬性來劃分消息的所屬類津函,劃分消息的這個類稱為 Topic肖粮。Topic 相當于消息的分類標簽,是一個邏輯概念尔苦。
物理上不同 Topic 的消息分開存儲涩馆,邏輯上一個 Topic 的消息雖然保存于一個或多個 Broker 上但用戶只需指定消息的 Topic 即可生產(chǎn)或消費數(shù)據(jù)而不必關心數(shù)據(jù)存于何處。Partition:分區(qū)允坚。Topic 中的消息被分割為一個或多個 Partition魂那,其是一個物理概念,對應到系統(tǒng)上 就是一個或若干個目錄屋讶。Partition 內(nèi)部的消息是有序的冰寻,但 Partition 間的消息是無序的。
Segment 段皿渗。
將 Partition 進一步細分為了若干的 Segment斩芭,每個 Segment 文件的大小相等。
Broker:
Kafka 集群包含一個或多個服務器乐疆,每個服務器節(jié)點稱為一個 Broker划乖。
Broker 存儲 Topic 的數(shù)據(jù)。如果某 Topic 有 N 個 Partition挤土,集群有 N 個 Broker琴庵,那么每個 Broker 存儲該 Topic 的一個 Partition。如果某 Topic 有 N 個 Partition仰美,集群有(N+M)個 Broker迷殿,那么其中有 N 個 Broker 存儲該 Topic 的一個 Partition,剩下的 M 個 Broker 不存儲該 Topic 的 Partition 數(shù)據(jù)咖杂。如果某 Topic 有 N 個 Partition庆寺,集群中 Broker 數(shù)目少于 N 個,那么一個 Broker 存儲該 Topic 的一個或多個 Partition诉字。在實際生產(chǎn)環(huán)境中懦尝,盡量避免這種情況的發(fā)生知纷,這種情況容易導致 Kafka 集群數(shù)據(jù)不均衡。
Producer:生產(chǎn)者
即消息的發(fā)布者陵霉,生產(chǎn)者將數(shù)據(jù)發(fā)布到他們選擇的主題琅轧。
生產(chǎn)者負責選擇將哪個記錄分配給主題中的哪個分區(qū)。即:生產(chǎn)者生產(chǎn)的一條消息踊挠,會被寫入到某一個 Partition乍桂。
Consumer:消費者
可以從 Broker 中讀取消息。一個消費者可以消費多個 Topic 的消息止毕;一個消費者可以消費同一個 Topic 中的多個 Partition 中的消息模蜡;一個 Partiton 允許多個 Consumer 同時消費。
Consumer Group:
Consumer Group 是 Kafka 提供的可擴展且具有容錯性的消費者機制扁凛。
組內(nèi)可以有多個消費者忍疾,它們共享一個公共的 ID,即 Group ID谨朝。組內(nèi)的所有消費者協(xié)調(diào)在一起來消費訂閱主題 的所有分區(qū)卤妒。
Kafka 保證同一個 Consumer Group 中只有一個 Consumer 會消費某條消息。實際上字币,Kafka 保證的是穩(wěn)定狀態(tài)下每一個 Consumer 實例只會消費某一個或多個特定的 Partition则披,而某個 Partition 的數(shù)據(jù)只會被某一個特定的 Consumer 實例所消費。
下面我們用官網(wǎng)的一張圖, 來標識 Consumer 數(shù)量和 Partition 數(shù)量的對應關系洗出。
由兩臺服務器組成的 Kafka 群集士复,其中包含四個帶有兩個使用者組的分區(qū)(P0-P3)。消費者組 A 有兩個消費者實例翩活,組 B 有四個阱洪。
對于這個消費組, 以前一直搞不明白, 我自己的總結是:
Topic 中的 Partitoin 到 Group 是發(fā)布訂閱的通信方式。
即一條 Topic 的 Partition 的消息會被所有的 Group 消費菠镇,屬于一對多模式冗荸;Group 到 Consumer 是點對點通信方式,屬于一對一模式。
舉個例子:
不使用 Group 的話,啟動 10 個 Consumer 消費一個 Topic煌妈,這 10 個 Consumer 都能得到 Topic 的所有數(shù)據(jù),相當于這個 Topic 中的任一條消息被消費 10 次程癌。使用 Group 的話,連接時帶上 groupid轴猎,Topic 的消息會分發(fā)到 10 個 Consumer 上席楚,每條消息只被消費 1 次。
Replizcas of partition:分區(qū)副本税稼。
副本是一個分區(qū)的備份烦秩,是為了防止消息丟失而創(chuàng)建的分區(qū)的備份。
Partition Leader:
每個 Partition 有多個副本郎仆,其中有且僅有一個作為 Leader只祠,Leader 是當前負責消息讀寫 的 Partition。即所有讀寫操作只能發(fā)生于 Leader 分區(qū)上扰肌。
Partition Follower:所有 Follower 都需要從 Leader 同步消息抛寝,F(xiàn)ollower 與 Leader 始終保持消息同步。Leader 與 Follower 的關系是主備關系曙旭,而非主從關系盗舰。
ISR:
ISR,In-Sync Replicas桂躏,是指副本同步列表钻趋。ISR 列表是由 Leader 負責維護。
AR剂习,Assigned Replicas蛮位,指某個 Partition 的所有副本, 即已分配的副本列表。
OSR鳞绕,Outof-Sync Replicas失仁,即非同步的副本列表。
AR=ISR+OSR
Offset:偏移量们何。
每條消息都有一個當前 Partition 下唯一的 64 字節(jié)的 Offset萄焦,它是相當于當前分區(qū)第一條消息的偏移量。
Broker Controller:
Kafka集群的多個 Broker 中冤竹,有一個會被選舉 Controller拂封,負責管理整個集群中 Partition 和 Replicas 的狀態(tài)。
只有 Broker Controller 會向 Zookeeper 中注冊 Watcher贴见,其他 Broker 及分區(qū)無需注冊烘苹。即 Zookeeper 僅需監(jiān)聽 Broker Controller 的狀態(tài)變化即可。
HW 與 LEO:
HW片部,HighWatermark镣衡,高水位,表示 Consumer 可以消費到的最高 Partition 偏移量档悠。HW 保證了 Kafka 集群中消息的一致性廊鸥。確切地說,是保證了 Partition 的 Follower 與 Leader 間數(shù) 據(jù)的一致性辖所。
LEO惰说,Log End Offset,日志最后消息的偏移量缘回。消息是被寫入到 Kafka 的日志文件中的吆视, 這是當前最后一個寫入的消息在 Partition 中的偏移量典挑。
對于 Leader 新寫入的消息,Consumer 是不能立刻消費的啦吧。Leader 會等待該消息被所有 ISR 中的 Partition Follower 同步后才會更新 HW您觉,此時消息才能被 Consumer 消費。
我相信你看完上面的概念還是懵逼的授滓,好吧琳水!下面我們就用圖來形象話的表示兩者的關系吧:
Zookeeper:
Zookeeper 負責維護和協(xié)調(diào) Broker,負責 Broker Controller 的選舉般堆。在 Kafka 0.9 之前版本在孝,Offset 是由 ZK 負責管理的。
總結:
ZK 負責 Controller 的選舉淮摔,Controller 負責 Leader 的選舉私沮。
Coordinator:
一般指的是運行在每個 Broker 上的 Group Coordinator 進程,用于管理 Consumer Group 中的各個成員噩咪,主要用于 Offset 位移管理和 Rebalance顾彰。一個 Coordinator 可以同時管理多個消費者組。
Rebalance:
當消費者組中的數(shù)量發(fā)生變化涨享,或者 Topic 中的 Partition 數(shù)量發(fā)生了變化時,Partition 的所有權會在消費者間轉移仆百,即 Partition 會重新分配厕隧,這個過程稱為再均衡 Rebalance。
再均衡能夠給消費者組及 Broker 帶來高性能俄周、高可用性和伸縮吁讨,但在再均衡期間消費者是無法讀取消息的,即整個 Broker 集群有小一段時間是不可用的峦朗。因此要避免不必要的再均衡建丧。Offset Commit:Consumer 從 Broker 中取一批消息寫入 Buffer 進行消費,在規(guī)定的時間內(nèi)消費完消息后翎朱,會自動將其消費消息的 Offset 提交給 Broker,以記錄下哪些消息是消費過的凛忿。當然委乌,若在時限內(nèi)沒有消費完畢,其是不會提交 Offset 的。
Kafka的工作原理和過程
①消息寫入算法
消息發(fā)送者將消息發(fā)送給 Broker, 并形成最終的可供消費者消費的 log暂吉,是已給比較復雜的過程:
Producer 先從 Zookeeper 中找到該 Partition 的 Leader。
Producer將消息發(fā)送給該 Leader嫉父。
Leader 將消息接入本地的 log仪际,并通知 ISR 的 Followers赴恨。
ISR 中的 Followers 從 Leader 中 Pull 消息, 寫入本地 log 后向 Leader 發(fā)送 Ack。
Leader 收到所有 ISR 中的 Followers 的 Ack 后,增加 HW 并向 Producer 發(fā)送 Ack,表示消息寫入成功。
②消息路由策略
在通過 API 方式發(fā)布消息時朱躺,生產(chǎn)者是以 Record 為消息進行發(fā)布的盈滴。Record 中包含 Key 與 Value硫朦,Value 才是我們真正的消息本身破婆,而 Key 用于路由消息所要存放的 Partition抛丽。消息要寫入到哪個 Partition 并不是隨機的蒿柳,而是有路由策略的:
若指定了 Partition仔引,則直接寫入到指定的 Partition版保。
若未指定 Partition 但指定了 Key,則通過對 Key 的 Hash 值與 Partition 數(shù)量取模豺型,該取模碉咆。
結果就是要選出的 Partition 索引。
若 Partition 和 Key 都未指定,則使用輪詢算法選出一個 Partition他爸。
③HW 截斷機制
如果 Partition Leader 接收到了新的消息, ISR 中其它 Follower 正在同步過程中馆类,還未同步完畢時 leader 宕機句喜。此時就需要選舉出新的 Leader。若沒有 HW 截斷機制咳胃,將會導致 Partition 中 Leader 與 Follower 數(shù)據(jù)的不一致展懈。當原 Leader 宕機后又恢復時,將其 LEO 回退到其宕機時的 HW涕蚤,然后再與新的 Leader 進行數(shù)據(jù)同步,這樣就可以保證老 Leader 與新 Leader 中數(shù)據(jù)一致了,這種機制稱為 HW 截斷機制泻云。
④消息發(fā)送的可靠性
生產(chǎn)者向 Kafka 發(fā)送消息時艇拍,可以選擇需要的可靠性級別。通過 request.required.acks 參數(shù)的值進行設置婆瓜。0 值:異步發(fā)送快集。生產(chǎn)者向 Kafka 發(fā)送消息而不需要 Kafka 反饋成功 Ack贡羔。該方式效率最高,但可靠性最低个初。其可能會存在消息丟失的情況:
在傳輸過程中會出現(xiàn)消息丟失乖寒。
在 Broker 內(nèi)部會出現(xiàn)消息丟失。
會出現(xiàn)寫入到 Kafka 中的消息的順序與生產(chǎn)順序不一致的情況院溺。
1 值:同步發(fā)送楣嘁。生產(chǎn)者發(fā)送消息給 Kafka,Broker 的 Partition Leader 在收到消息后馬上發(fā)送成功 Ack(無需等等 ISR 中的 Follower 同步)覆获。生產(chǎn)者收到后知道消息發(fā)送成功马澈,然后會再發(fā)送消息。如果一直未收到 Kafka 的 Ack弄息,則生產(chǎn)者會認為消息發(fā)送失敗痊班,會重發(fā)消息。該方式對于 Producer 來說摹量,若沒有收到 Ack涤伐,一定可以確認消息發(fā)送失敗了,然后可以重發(fā)缨称。但是凝果,即使收到了 ACK,也不能保證消息一定就發(fā)送成功了睦尽。故器净,這種情況,也可能會發(fā)生消息丟失的情況当凡。-1 值:同步發(fā)送山害。生產(chǎn)者發(fā)送消息給 Kafka,Kafka 收到消息后要等到 ISR 列表中的所有副本都 同步消息完成后沿量,才向生產(chǎn)者發(fā)送成功 Ack浪慌。如果一直未收到 Kafka 的 Ack,則認為消息發(fā)送 失敗朴则,會自動重發(fā)消息权纤。該方式會出現(xiàn)消息重復接收的情況。
⑤消費者消費過程解析
生產(chǎn)者將消息發(fā)送到 Topitc 中乌妒,消費者即可對其進行消費汹想,其消費過程如下:
Consumer 向 Broker 提交連接請求,其所連接上的 Broker 都會向其發(fā)送Broker Controller 的通信 URL芥被,即配置文件中的 Listeners 地址欧宜。
當 Consumer 指定了要消費的 Topic 后,會向 Broker Controller 發(fā)送消費請求拴魄。
Broker Controller 會為 Consumer 分配一個或幾個 Partition Leader冗茸,并將該 Partition 的當前 Offset 發(fā)送給 Consumer席镀。
Consumer 會按照 Broker Controller 分配的 Partition 對其中的消息進行消費。
當 Consumer 消費完該條消息后夏漱,Consumer 會向 Broker 發(fā)送一個消息已經(jīng)被消費反饋豪诲,即該消息的 Offset。
在 Broker 接收到 Consumer 的 Offset 后挂绰,會更新相應的 __consumer_offset 中屎篱。
以上過程會一直重復,知道消費者停止請求消費葵蒂。
Consumer 可以重置 Offset交播,從而可以靈活消費存儲在 Broker 上的消息。
⑥Partition Leader 選舉范圍
當 Leader 宕機后践付,Broker Controller 會從 ISR 中挑選一個 Follower 成為新的 Leader秦士。如果 ISR 中沒有其他副本怎么辦?可以通過 unclean.leader.election.enable 的值來設置 Leader 選舉范圍永高。False:必須等到 ISR 列表中所有的副本都活過來才進行新的選舉隧土。該策略可靠性有保證,但可用性低命爬。True:在 ISR 列表中沒有副本的情況下曹傀,可以選擇任意一個沒有宕機的主機作為新的 Leader,該策略可用性高饲宛,但可靠性沒有保證皆愉。
⑦重復消費問題的解決方案
同一個 Consumer 重復消費:當 Consumer 由于消費能力低而引發(fā)了消費超時,則可能會形成重復消費艇抠。
在某數(shù)據(jù)剛好消費完畢亥啦,但是正準備提交 Offset 時候,消費時間超時练链,則 Broker 認為這條消息未消費成功。這時就會產(chǎn)生重復消費問題奴拦。其解決方案:延長 Offset 提交時間媒鼓。
不同的 Consumer 重復消費:當 Consumer 消費了消息,但還沒有提交 Offset 時宕機错妖,則這些已經(jīng)被消費過的消息會被重復消費绿鸣。其解決方案:將自動提交改為手動提交。
作者:凌晶
簡介:生活中的段子手暂氯,目前就職于一家地產(chǎn)公司做 Devops 相關工作潮模,曾在大型互聯(lián)網(wǎng)公司做高級運維工程師,熟悉 Linux 運維痴施,Python 運維開發(fā)擎厢,Java 開發(fā)究流,Devops 常用開發(fā)組件等,個人公眾號:stromling动遭,歡迎來撩我哦芬探!