訊息佇列實現原理(以kafka為例)

2021-10-09 15:29:38 字數 3004 閱讀 8135

訊息佇列中介軟體是分布式系統中重要的元件,主要解決應用耦合,非同步訊息,流量削鋒等問題。實現高效能、高可用、可伸縮和最終一致性架構。使用較多的訊息佇列有kafka、activemq、rabbitmq、zeromq、metamq、rocketmq。

訊息佇列在實際應用中常用的使用場景:非同步處理,應用解耦,流量削鋒和訊息通訊四個場景。

1、非同步處理:使用者註冊後,需要發註冊郵件和註冊簡訊。

2、應用解耦:使用者下單後,訂單系統需要通知庫存系統。

3、流量削鋒:秒殺活動,一般會因為流量過大,導致流量暴增,應用掛掉。為解決這個問題,一般需要在應用前端加入訊息佇列。可以控制活動的人數,可以緩解短時間內高流量壓垮應用。

4、日誌採集:日誌採集端將日誌寫入kafka隊裡,開啟多個執行緒消費日誌佇列,做進一步處理。

kafka 是一款分布式流處理框架,用於實時構建流處理應用。它有乙個核心 的功能廣為人知,即作為企業級的訊息引擎被廣泛使用。kafka是一種高吞吐量的分布式發布訂閱訊息系統,它可以處理消費者規模的**中的所有動作流資料,具有高效能、持久化、多副本備份、橫向擴充套件能力。下圖是kafka的架構圖:

producer:producer即生產者,訊息的產生者,是訊息的入口。

consumer:消費者,即訊息的消費方,是訊息的出口。

consumer group:我們可以將多個消費組組成乙個消費者組,在kafka的設計中同乙個分割槽的資料只能被消費者組中的某乙個消費者消費。同乙個消費者組的消費者可以消費同乙個topic的不同分割槽的資料,這也是為了提高kafka的吞吐量!

message:每一條傳送的訊息主體。

kafka cluster(集群):

broker:broker是kafka例項,每個伺服器上有乙個或多個kafka的例項,我們姑且認為每個broker對應一台伺服器。每個kafka集群內的broker都有乙個不重複的編號,如圖中的broker-0、broker-1等……

topic:訊息的主題,可以理解為訊息的分類,kafka的資料就儲存在topic。在每個broker上都可以建立多個topic。

partition:topic的分割槽,每個topic可以有多個分割槽,分割槽的作用是做負載均衡,提高kafka的吞吐量。同乙個topic在不同的分割槽的資料是不重複的,partition的表現形式就是乙個乙個的資料夾!

replication:每乙個分割槽都有多個副本,副本的作用是做備胎。當主分割槽(leader)故障的時候會選擇乙個備胎(follower)上位,成為leader。在kafka中預設副本的最大數量是10個,且副本的數量不能大於broker的數量,follower和leader絕對是在不同的機器,同一機器對同乙個分割槽也只可能存放乙個副本(包括自己)。

zookeeper:kafka集群依賴zookeeper來儲存集群的的元資訊,來保證系統的可用性。比如檢測broker是否存活等作用。

在介紹 leader 選舉之前,讓我們先來了解一下 isr(in-sync replicas)列表。每個分割槽的 leader 會維護乙個 isr 列表,isr 列表裡面就是 follower 副本的 borker 編號,只有跟得上 leader 的 follower 副本才能加入到 isr 裡面,這個是通過 replica.lag.time.max.ms 引數配置的。只有 isr 裡的成員才有被選為 leader 的可能。

leader 掛掉了,kafka 會從 isr 列表中選擇第乙個 follower 作為新的 leader,因為這個分割槽擁有最新的已經 committed 的訊息。通過這個可以保證已經 committed 的訊息的資料可靠性。

這裡介紹的資料一致性主要是說不論是老的 leader 還是新選舉的 leader(原來的follower),consumer 都能讀到一樣的資料。那麼 kafka 是如何實現的呢?

假設分割槽的副本為3,其中副本0是 leader,副本1和副本2是 follower,並且在 isr 列表裡面。雖然副本0已經寫入了 message4,但是 consumer 只能讀取到 message2。因為所有的 isr 都同步了 message2,只有 high water mark 以上的訊息才支援 consumer 讀取,而 high water mark 取決於 isr 列表裡面偏移量最小的分割槽,對應於上圖的副本2,這個很類似於木桶原理。

這樣做的原因是還沒有被足夠多副本複製的訊息被認為是「不安全」的,如果 leader 發生崩潰,另乙個副本成為新 leader,那麼這些訊息很可能丟失了。如果我們允許消費者讀取這些訊息,可能就會破壞一致性。試想,乙個消費者從當前 leader(副本0) 讀取並處理了 message4,這個時候 leader 掛掉了,選舉了副本1為新的 leader,這時候另乙個消費者再去從新的 leader 讀取訊息,發現這個訊息其實並不存在,這就導致了資料不一致性問題。

當然,引入了 high water mark 機制,會導致 broker 間的訊息複製因為某些原因變慢,那麼訊息到達消費者的時間也會隨之變長(因為我們會先等待訊息複製完畢)。延遲時間可以通過引數 replica.lag.time.max.ms 引數配置,它指定了副本在複製訊息時可被允許的最大延遲時間。

上面說到一致性原理,那麼在kafka如何將leader的資料同步到follow的呢?

follower非同步地從leader複製資料,資料只要被leader寫入log就被認為已經commit,這種情況下,如果leader掛掉,會丟失資料,kafka使用isr的方式很好的均衡了確保資料不丟失以及吞吐率。follower可以批量的從leader複製資料,而且leader充分利用磁碟順序讀以及send file(zero copy)機制,這樣極大的提高複製效能,內部批量寫磁碟,大幅減少了follower與leader的訊息量差。

kafka每個partition中的訊息在寫入時都是有序的,消費時,每個partition只能被每乙個group中的乙個消費者消費,保證了消費時也是有序的。

整個topic不保證有序。如果為了保證topic整個有序,那麼將partition調整為1。

訊息佇列 訊息佇列 kafka

kafka是乙個分布式的基於發布 訂閱模式的訊息佇列,主要用於大資料實時處理領域。要理解kafka首先要有分布式的概念,要有訊息佇列的概念。分布式系統最大的優勢就是解耦和削峰,這種情況下,a系統生成了乙個訊息,b系統非同步獲取,那麼就需要乙個存放訊息的訊息佇列 mq 相比較傳統的訊息佇列,訊息被消費...

訊息佇列 Kafka學習

kafka是乙個分布式的訊息佇列,學習見apache kafka文件,中文翻譯見kafka分享,乙個簡單的入門例子見kafka 入門例項。本文只針對自己感興趣的點記錄下。producer consumer 訊息的生成者和使用者。broker kafka server充當broker角色,起到訊息佇列...

訊息佇列 Kafka學習

kafka是乙個分布式的訊息佇列,學習見apache kafka文件,中文翻譯見kafka分享,乙個簡單的入門例子見kafka 入門例項。本文只針對自己感興趣的點記錄下。producer consumer 訊息的生成者和使用者。broker kafka server充當broker角色,起到訊息佇列...