Kafka實戰(二)-Kafka消息模型核心概念
Kafka是分布式的,基于發布訂閱的消息系統。
1 特點
同時為發布和訂閱提供高吞吐量
Kafka每秒可生產約25萬條消息(50 MB),每秒處理55萬條消息(110 MB)
持久化
默認就將消息持久化到磁盤,因此可用于批量消費,例如ETL,以及實時應用程序。通過將數據持久化到硬盤以及防止數據丟失。以O(1)時間復雜度提供消息持久化能力,即使對TB級以上數據也能保證常數時間復雜度的訪問性能。
分布式系統,易于向外擴展
所有的producer、broker和consumer都會有多個,均為分布式的。無需停機即可擴展機器。消息被處理的狀態是在consumer端維護,而不是由server端維護。當失敗時能自動平衡
支持online和offline場景
Kafka發布訂閱的對象是主題(Topic),可為每個業務、每個應用甚至是每類數據都創建專屬的主題。
Message
消息,是通信的基本單位,每個producer可以向一個topic(主題)發布一些消息
1 Producer & Consumer(客戶端)
生產者(Producer)
向主題發布消息的客戶端應用。生產者程序通常持續不斷向一或多個主題發消息。
消費者(Consumer)
訂閱這些主題消息的客戶端應用程序。消費者也能同時訂閱多個主題消息。
生產者和消費者統稱為客戶端(Clients)。可同時運行多個生產者和消費者實例,這些實例會不斷向Kafka集群中的多個主題生產和消費消息。
2 Broker(服務器端)
Kafka的服務器端由被稱為Broker的服務進程構成,即一個Kafka集群由多個Broker組成。
Broker負責接收和處理客戶端發送過來的請求,以及對消息進行持久化。
雖然多個Broker進程能夠運行在同一機器,但更常見的做法是將不同的Broker分散運行在不同機器。
這樣如集群中某一機器宕機,即使在它上面運行的所有Broker進程都掛,其他機器的Broker也依然能夠對外提供服務。
這也是Kafka高可用的手段之一。
3 Partitioning(分區)
partition,物理上的概念,有序不可變的record序列,partition中的record會被分配一個自增長id(offset)。
一個topic中的消息數據按照多個分區組織,partition是kafka消息隊列組織的最小單位,一個partition可看做是一個隊列。
雖然副本機制可保證數據持久化以不丟消息,但未解決Scalability伸縮性問題。
雖現在有leader、follower副本,但若leader副本積累太多數據以至單臺Broker無法容納,何如?
Kafka就會把數據分割成多份保存在不同Broker,即分區。類似其他分布式系統的分片、分區域等提法,比如
MongoDB和Elasticsearch中的Sharding
HBase中的Region
都是相同原理,但Partitioning才是最標準名稱。
Kafka分區是將每個topic劃成多個分區(Partition),每個Partition內是一組順序消息日志。
生產者生產的每條消息只會被發送到一個分區,即向一個雙分區的主題發送一條消息,該消息要么在分區0,要么在分區1(分區編號從0開始)。
副本與分區
副本是在分區級別定義的。
每個分區下可配置若干個副本,其中只能有1個領導者副本和N-1個追隨者副本。
生產者向分區寫入消息,每條消息在分區中的位置信息由一個叫位移(Offset)的數據來表征。
分區位移總是從0開始,假設一個生產者向一個空分區寫入了10條消息,那么這10條消息的位移依次是0、1、2、…、9。
4 Topic
一個業務即一個Topic。
每條發布到Kafka集群的消息都有一個類別,這個類別被稱為Topic。物理上不同Topic的消息分開存儲,邏輯上一個Topic的消息雖保存于一或多個broker,但用戶只需指定消息的Topic即可生產或消費數據,不必關心數據存于何處。
數據主題,是Kafka中用來代表一個數據流的一個抽象,Kafka處理的消息源(feeds of messages)的不同分類。
發布數據時,可用topic對數據分類,也作為訂閱數據時的主題。
一個Topic同時可有多個producer、consumer。
Topic可理解為一個隊列,生產者和消費者面向的都是同一topic。
5 3 Replication - 副本
實現高可用的另一個手段。
為保證分布式可靠性,kafka0.8開始對每個分區的數據進行備份(不同Broker上),防止其中一個Broker宕機造成分區數據不可用。
每個partition被復制到其它服務器作為replication,這是一種冗余備份策略
同一partition的多個replication不允許在同一broker
每個partition的replication中,有一個leader,零或多follower
leader處理此分區所有的讀寫請求
follower僅被動的復制數據
leader宕機后,會從follower中選舉出新的leader
副本數量是可配置的,副本保存著相同的數據,卻有不同
3.1 副本的分類
Kafka定義了兩類副本
領導者副本(Leader Replica)
對外提供服務,與客戶端程序交互
追隨者副本(Follower Replica)
只被動地追隨領導者副本,不與外界交互
在很多其他系統中追隨者副本是可以對外提供服務的,比如MySQL的從庫是可以處理讀操作的,但是在Kafka中追隨者副本不會對外提供服務。
3.2 副本的工作機制
生產者總是向領導者副本寫消息
而消費者總是從領導者副本讀消息
至于追隨者副本,它只做一件事:向領導者副本發送請求,請求領導者把最新生產的消息發給它,這樣它能保持與領導者的同步。
6 Record
每條記錄都有key、value、 timestamp三個信息
分區id+offset才可確定數據位置
分區內才是有序的!
ConsumerGroup - 消費組
每個Consumer屬于一個特定的Consumer Group (可為每個Consumer 指定 group name, 若不指定 group name則屬于默認的group)
消費者可使用相同的 group.id 加入一個組
每個Consumer實例屬于一個ConsumerGroup
組的最大并行度是組中的消費者數量 ← 沒有partition
Kafka將topic的partition分配給組中的消費者,以便每個分區僅由組中的一個消費者使用
Kafka保證消息只能由該組中的單個消費者讀取。消費者可按存儲在日志中的順序查看消息
每個ConsumerGroup都有一個Coordinator(協調者),負責分配Consumer和Partition的對應關系,當Partition或是Consumer發生變更時,會觸發reblance(重新分配),重新分配Consumer與Partition的對應關系
Coordinator
Consumer維護與Coordinator之間的心跳,這樣Coordinator就能感知到Consumer的狀態,在Consumer故障的時候及時觸發rebalance。
Kafka的三層消息架構
第一層是主題層,每個主題可以配置M個分區,而每個分區又可以配置N個副本
第二層是分區層,每個分區的N個副本中只能有一個充當領導者角色,對外提供服務;其他N-1個副本是追隨者副本,只是提供數據冗余之用
第三層是消息層,分區中包含若干條消息,每條消息的位移從0開始,依次遞增
最后,客戶端程序只能與分區的領導者副本進行交互。
講完了消息層次,來說說Kafka Broker是如何持久化數據的。總的來說,Kafka使用消息日志(Log)來保存數據,一個日志就是磁盤上一個只能追加寫(Append-only)消息的物理文件。因為只能追加寫入,故避免了緩慢的隨機I/O操作,改為性能較好的順序I/O寫操作,這也是實現Kafka高吞吐量特性的一個重要手段。不過如果你不停地向一個日志寫入消息,最終也會耗盡所有的磁盤空間,因此Kafka必然要定期地刪除消息以回收磁盤。怎么刪除呢?簡單來說就是通過日志段(Log Segment)機制。在Kafka底層,一個日志又近一步細分成多個日志段,消息被追加寫到當前最新的日志段中,當寫滿了一個日志段后,Kafka會自動切分出一個新的日志段,并將老的日志段封存起來。Kafka在后臺還有定時任務會定期地檢查老的日志段是否能夠被刪除,從而實現回收磁盤空間的目的。
這里再重點說說消費者。
點對點模型(Peer to Peer,P2P)和發布訂閱模型。這里面的點對點指的是同一條消息只能被下游的一個消費者消費,其他消費者則不能染指。在Kafka中實現這種P2P模型的方法就是引入了消費者組(Consumer Group)。所謂的消費者組,指的是多個消費者實例共同組成一個組來消費一組主題。這組主題中的每個分區都只會被組內的一個消費者實例消費,其他消費者實例不能消費它。為什么要引入消費者組呢?主要是為了提升消費者端的吞吐量。多個消費者實例同時消費,加速整個消費端的吞吐量(TPS)。我會在專欄的后面詳細介紹消費者組機制,所以現在你只需要了解消費者組是做什么的即可。另外這里的消費者實例可以是運行消費者應用的進程,也可以是一個線程,它們都稱為一個消費者實例(Consumer Instance)。
消費者組里面的所有消費者實例不僅“瓜分”訂閱主題的數據,而且更酷的是它們還能彼此協助。假設組內某個實例掛掉了,Kafka能夠自動檢測到,然后把這個Failed實例之前負責的分區轉移給其他活著的消費者。這個過程就是Kafka中大名鼎鼎的“重平衡”(Rebalance)。嗯,其實既是大名鼎鼎,也是臭名昭著,因為由重平衡引發的消費者問題比比皆是。事實上,目前很多重平衡的Bug社區都無力解決。
每個消費者在消費消息的過程中必然需要有個字段記錄它當前消費到了分區的哪個位置上,這個字段就是消費者位移(Consumer Offset)。注意,這和上面所說的位移完全不是一個概念。上面的“位移”表征的是分區內的消息位置,它是不變的,即一旦消息被成功寫入到一個分區上,它的位移值就是固定的了。而消費者位移則不同,它可能是隨時變化的,畢竟它是消費者消費進度的指示器嘛。另外每個消費者有著自己的消費者位移,因此一定要區分這兩類位移的區別。我個人把消息在分區中的位移稱為分區位移,而把消費者端的位移稱為消費者位移。
8 總結
消息:Record。Kafka是消息引擎嘛,這里的消息就是指Kafka處理的主要對象。
主題:Topic。主題是承載消息的邏輯容器,在實際使用中多用來區分具體的業務。
分區:Partition。一個有序不變的消息序列。每個主題下可以有多個分區。
消息位移:Offset。表示分區中每條消息的位置信息,是一個單調遞增且不變的值。
副本:Replica。Kafka中同一條消息能夠被拷貝到多個地方以提供數據冗余,這些地方就是所謂的副本。副本還分為領導者副本和追隨者副本,各自有不同的角色劃分。副本是在分區層級下的,即每個分區可配置多個副本實現高可用。
生產者:Producer。向主題發布新消息的應用程序。
消費者:Consumer。從主題訂閱新消息的應用程序。
消費者位移:Consumer Offset。表征消費者消費進度,每個消費者都有自己的消費者位移。
消費者組:Consumer Group。多個消費者實例共同組成的一個組,同時消費多個分區以實現高吞吐。
重平衡:Rebalance。消費者組內某個消費者實例掛掉后,其他消費者實例自動重新分配訂閱主題分區的過程。Rebalance是Kafka消費者端實現高可用的重要手段。
9 為什么Kafka不像MySQL允許追隨者副本對外提供讀服務?
不從follower讀幾個原因:1,kafka的分區已經讓讀是從多個broker讀從而負載均衡,不是MySQL的主從,壓力都在主上;2,kafka保存的數據和數據庫的性質有實質的區別就是數據具有消費的概念,是流數據,kafka是消息隊列,所以消費需要位移,而數據庫是實體數據不存在這個概念,如果從kafka的follower讀,消費端offset控制更復雜;3,生產者來說,kafka可以通過配置來控制是否等待follower對消息確認的,如果從上面讀,也需要所有的follower都確認了才可以回復生產者,造成性能下降,如果follower出問題了也不好處理
首先明確一下:主從分離與否沒有絕對的優劣,它僅僅是一種架構設計,各自有適用的場景。
第二、如你所說,Redis和MySQL都支持主從讀寫分離,我個人覺得這和它們的使用場景有關。對于那種讀操作很多而寫操作相對不頻繁的負載類型而言,采用讀寫分離是非常不錯的方案——我們可以添加很多follower橫向擴展,提升讀操作性能。反觀Kafka,它的主要場景還是在消息引擎而不是以數據存儲的方式對外提供讀服務,通常涉及頻繁地生產消息和消費消息,這不屬于典型的讀多寫少場景,因此讀寫分離方案在這個場景下并不太適合。
第三、Kafka副本機制使用的是異步消息拉取,因此存在leader和follower之間的不一致性。如果要采用讀寫分離,必然要處理副本lag引入的一致性問題,比如如何實現read-your-writes、如何保證單調讀(monotonic reads)以及處理消息因果順序顛倒的問題。相反地,如果不采用讀寫分離,所有客戶端讀寫請求都只在Leader上處理也就沒有這些問題了——當然最后全局消息順序顛倒的問題在Kafka中依然存在,常見的解決辦法是使用單分區,其他的方案還有version vector,但是目前Kafka沒有提供。最后、社區正在考慮引入適度的讀寫分離方案,比如允許某些指定的follower副本(主要是為了考慮地理相近性)可以對外提供讀服務。當然目前這個方案還在討論中
參考
《Apache Kafka實戰》
https://www.zhihu.com/question/327925275/answer/705690755
https://kafka.apache.org/documentation
Kafka 分布式
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。