kafka簡介一(初識kafka)


從這一章節開始,我們開始學習MQ kafka。

簡介

Apache Kafka 是Apache軟件基金會的開源的流處理平臺,提供了消息的訂閱與發佈,是一種消息隊列,一般的作用如下:

  • 系統間解耦
  • 異步通信
  • 削峯填谷

爲了方便理解,舉個例子:
現有一個系統,會員登錄之後,如果發現當前是會員的生日,則通過郵件發送祝福。
在這裏插入圖片描述
很明顯這個流程是有問題的:

  1. 將發送祝福的邏輯,與用戶等了進行強耦合,是否合適?
  2. 如果用戶等了成功,但是 短信/郵件 網關出現故障了,導致祝福沒有發送出去,用戶始終在等待登錄結果,是否合適?

顯然這兩種情況都不合適,如果我們在中間加入消息隊列:
在這裏插入圖片描述
用戶登錄即刻通知用戶登錄成功,同時將登錄消息放入消息隊列,通過異步方式通知後續的短信,郵件服務,在服務內部判斷是否生日,然後再發送祝福。即便網關出現問題,並不影響用戶的登錄。

削峯填谷,主要是用在大數據的流處理中,避免同一時間的超大量請求打爆服務。

消息隊列(MQ)

上面已經講過了,kafka是一種消息隊列,那消息隊列又是啥呢?

消息隊列,是一種在分佈式和大數據開發中不可或缺的中間件,一般有下面兩種大類:

  • 至多一次:生產者將消息寫入隊列系統後,由消費者負責去拉取消息,一旦確定消息被消費之後,消息隊列系統需要主動刪除隊列中的數據,這種消費方式,一般只允許被一個消費者消費,並且隊列中的數據,不允許被重複消費。
  • 沒有限制:與上面不同,產生的消息,可以被多個消費者同時消費,並且同一個消費者可以多次消費消息服務器中的同一個記錄。

kafka架構

先介紹幾個名詞:

  • Record:記錄,即消息本身
  • Topic:消息的主題,Topic負責分類集羣中的Record,每一個Record都會歸屬於一個Topic。它是消息存儲的邏輯概念,是一類消息的集合,在物理上,不同的Topic的消息是分開存儲的。
  • Partition:分區,每一個Topic可以劃分爲多個Partition,同一個Topic下的不同分區消息是不一樣的,是將一個Topic下的數據進行了拆分存儲進不同的Partition,Topic是邏輯存儲概念,具體的磁盤存儲是基於Partition。
  • Borker:即一個kafka的實例,Topic的每一個分區,都一定會有一個Borker擔當該分區的leader,其他的Broker爲該分區的follower。
    leader負責分區數據的讀寫,follower負責同步該分區的數據。如果該分區的leader宕機,其他的follower會選出一個新的leader。
  • zookeeper:監控集羣中的leader,同時存儲Topic的部分元數控

在這裏插入圖片描述
生產者,將每一個Record指定Topic之後,發送給kafka集羣,消費者在訂閱了Topic之後,kafka將相應的Record推送給消費者。

在kafka內部,針對一個Topic,消息是如何存儲的呢?
在這裏插入圖片描述
上面我們已經提到過,每個Topic在存儲時,是按照Partition進行的,當生產者產生出一個Record之後,是如何決定數據最終落在哪個Partition呢?
一個Recode一般包含key,value以及這條消息的時間戳。
對key進行hash後,對分區的數量進行取模,取模結果即爲最終落的Partition。
假設現在一個topic下有3個分區,key的hash值爲4,那最終落的Partition爲4%3=1,即爲第一個分區。

那kafka又是如何對一個Topic下的所有數據進行存儲的呢?
假設現在kafka集羣有3個Broker,針對該Topic,每個Broker都會持有該Topic下的3個分區,以第一個分區Partition0爲例,Broker0爲Partition0的leader,Broker1,Broker2t同樣持有Partition0的數據,但是他們都是follower,一旦Broker0宕機了,Broker1和Broker2中的一臺會成爲新的leader,繼續對Partition0提供讀寫。這塊後面會詳細介紹。

那如果集羣中有5個Broker,是否每一個Broker都會有Partition0呢?並不是,一個Partition有多少個數據備份,是由 分區/副本 因子決定的,如果因子是3,則最多隻會有3份

存儲有序性

在這裏插入圖片描述
kafka保證每個Partition內的Record是有序的,每一個Record都被分配了一個唯一的編號offset,此即爲單分區有序。

是不是注意到了一個問題呢,消息以Topic進行發送,但是一個Topic下可以有多個Partition,單個Partition是有序的,那多個Partition會怎麼樣呢?答案是無序的。

比如:生產者發出了4條消息,Record1進入分區1,Record2進入分區2,Record3進入分區1,Record4進入分區3,僅能保證在分區1內,Record1和Record2是有序存儲的。
那如果4條消息,如何有序存儲呢?將4條消息依次寫入同一個Partition就可以了。或者該Topic只有一個分區,但是這個會影響消費的效率。

按照我們對於隊列的理解,應該都是先進先出的,但是目前看起來,kafka只能局部保證消息先進先出,那爲什麼kafka要搞出個分區的概念來破壞消息的先進先出機制呢?試想一下,如果一個Topic有100個Partition,每個Partition容量一個T,那那個Topic下就可以存儲100T的數據,而且有高可用的災備,是不是很激動?

存儲時效性

kafka會持久化Topic中的每個Record,持久化時間,默認是168小時,即7天時間。可以通過配置:log.retention.hours=168進行調整。
kafka會定期檢測日誌文件,將過期的數據從磁盤中移除。
之前很好奇爲什麼公司es的日誌查詢有效期是7天,大概率是因爲這個。

消費者消費數據

消費者在消費數據時,每個消費者都會維護本次消費對應的Partition的偏移量offset,消費者在消費完一個批次的數據之後,會將偏移量offset提交各kafka集羣。
可以看出,每個消費者是可以自定義消息的offset,有了從Topic的分區中任意位置拉取消息的能力,並且由於是各玩各的,故而每個消費者之間相互獨立。
在這裏插入圖片描述

消費組 Consumer Group

既然是一個group,那肯定是一個消費者的集合了。

想象一下:

  1. 如果一個Topic下有1T的數據等待消費,如果只有一個消費者,每一消費需要50ms,那得消費到啥時候去?
  2. 現在有一個Topic,有3個消費者,任何這3個消費者都想訂閱消費,咋通知呢?

這個時候,我們的Consumer Group便可以大顯身手了。可以簡單粗暴的理解爲一個group爲一個單獨的業務線。

舉一個簡單的例子,不一定貼切:
現在有一個合同(Topic),有兩家公司(Consumer group),每家公司下有10名員工(Consumer),兩家公司都想要這份合同(消費消息),咋辦呢?最後商議,兩家公司各處一名員工來處理合同。
至此,可以簡單的理解爲,一個Topic下的消息,發送到多個group,從每個group中挑選出一個Consumer來消費該Record。感覺還是蠻形象的哈~

結合上文所講,一個Topic有多個Partition,現在一個Consumer group下有多個Consumer,正好多對多,是不是可以建立聯繫呢?

在這裏插入圖片描述
一個Topic下的多個Partition,會均分到一個group中的每個customer,是不是沒看懂呢?
已上圖爲例:
一個Topic下有4個Partition,group1有2個customer,group2下有4個customer,咋分呢?
對於group1,2個customer要接管4個Partition,很顯然,一個customer負責消費2個Partition
對於group1,4個customer對4個Partition,正好,一對一。

還是上面這張圖,如有下面幾個問題:

  1. 一個Partition下的數據會不會同時被一個group下不同的customer消費:不能,這相當在一家公司A中,合同已經給了員工甲,但是員工乙偷偷地做,這種屬於重複消費。
  2. 一個Partition下的數據會不會同時被不同group下的customer消費:能,這種就是上文例子中的,一份合同,同時給了AB兩家公司的甲乙兩名員工。
  3. 同一個topic,group1和group2誰消費會快?很明顯是group2,group2中每一個customer只要消費處理一個Partition,而group1中每個customer卻需要處理2個Partition
  4. 如果在group2中再添加一名customer,能加快速度嗎?不能,因爲已經沒有多餘的Partition能給這個新增者來消費了。

通過以上幾個問題,我們可以得出結論,一般Partition的數量,等於group下的customer的數量,這種配比,效率是最高的。

高吞吐

kafka在普通機器上,都可以實現每秒百萬級的寫入,kafka是怎麼實現的呢?

  • 順序寫入
    磁盤寫入時IO費時間,主要是花在了”尋址“上面,機械硬盤需要不斷移動磁頭來寫入文件,隨機I/O會大大增加尋址的頻率。
    kafka文件順序寫入,大大節省了尋址時間。
  • mmap,重複利用操作系統的分頁存儲,利用內存來提高I/O效率。Memory Mapped Files,內存映射文件。將物理內存直接映射到操作系統內存,由操作系統實現從內存直接寫入磁盤。
  • 零拷貝:kafka在響應請求時,從磁盤讀取數據後,不將數據copy進用戶空間,而是直接在操作系統的內核空間直接將數據傳出去。
    在這裏插入圖片描述
    經典的通訊模型如圖,數據先從磁盤copy進內核空間,再從內核空間copy進用戶空間,再從應用層copy進網卡等socket buffer,最後再copy出通過網絡傳輸出去,中間經歷了4次copy。

在這裏插入圖片描述
零拷貝,不經過應用層,直接在內核內存中copy進buffer,減少一次無意義的copy。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章