Kafka的原理介紹及實踐

文|孫超後端

網易智慧企業資深後端開發工程師緩存

官方定義 安全

根據官網的介紹,kafka是一個提供統一的、高吞吐、低延遲的,用來處理實時數據的流式平臺,它具有如下三特性:服務器

  1. 流式記錄的發佈和訂閱:相似於消息系統。
  2. 存儲:在一個分佈式、容錯的集羣中安全持久化地存儲流式數據。
  3. 處理:編寫流處理應用程序,對實時事件進行響應。

kafka通常用在兩大類應用中:併發

  1. 創建實時流數據管道,在系統或應用之間實時地傳輸數據。
  2. 構建對數據流進行轉換和處理的實時流應用程序。

在郵箱服務中,咱們主要將kafka做爲消息系統,用於系統內部消息的傳輸。爲何要採用kafka呢?讓咱們先從kafka的設計原理提及。分佈式

概念與存儲機制 高併發

kafka中是以Topic機制來對消息進行分類的,同一類消息屬於同一個Topic,你能夠將每一個Topic當作是一個消息隊列。生產者將消息發送到相應的Topic,而消費者經過從Topic拉取消息來消費,沒錯,在kafka中是要求消費者主動拉取消息消費的,它並不會主動推送消息,這是它的一個特色,爲何會這樣設計呢?咱們後面再說,先來看一下Topic的結構:spa

Partition分區每一個topic能夠有多個分區,這是kafka爲了提升併發量而設計的一種機制:一個topic下的多個分區能夠併發接收消息,一樣的也能供消費者併發拉取消息,即分區之間互不干擾,這樣的話,有多少個分區就能夠有多大的併發量。因此,若是要更準確的打比方,一個分區就是一個消息隊列,只不過這些消息隊列同屬於一種消息分類。操作系統

在kafka服務器,分區是以目錄形式存在的,每一個分區目錄中,kafka會按配置大小或配置週期將分區拆分紅多個段文件(LogSegment), 每一個段由三部分組成:線程

  1. 磁盤文件:*.log
  2. 位移索引文件:*.index
  3. 時間索引文件:*.timeindex

其中*.log用於存儲消息自己的數據內容,*.index存儲消息在文件中的位置(包括消息的邏輯offset和物理存儲offset),*.timeindex存儲消息建立時間和對應邏輯地址的映射關係。

段文件結構圖以下 :

將分區拆分紅多個段是爲了控制存儲的文件大小,若是整個分區只保存爲一個文件,那隨着分區裏消息的增多,文件也將愈來愈大,最後不可控制。而若是每一個消息都保存爲一個文件,那文件數量又將變得巨大,一樣容易失去控制。因此kafka採用段這種方式,控制了每一個文件的大小,也方便控制全部文件的數量。同時,這些文件由於大小適中,能夠很方便地經過操做系統mmap機制映射到內存中,提升寫入和讀取效率。這個設計的另外一個好處是:當系統要清除過時數據時,能夠直接將過時的段文件刪除,很是簡潔。

可是這裏也會有一個問題:若是每一個消息都要在index文件中保存位置信息,那麼index文件也很容易變得很大,這樣又會減弱上文所說的好處。因此在kafka中,index設計爲稀疏索引來下降index的文件大小,這樣,index文件存儲的實際內容爲:該段消息在消息隊列中的相對offset和在log文件中的物理偏移量映射的稀疏記錄。

那麼多少條消息會在index中保存一條記錄呢?這個能夠經過系統配置來進行設置。索引記錄固定爲8個字節大小,分別爲4個字節的相對offset(消息在partition中全局offset減去該segment的起始offset),4個字節的消息具體存儲文件的物理偏移量。

index文件結構圖以下:

Kafka不會在消費者拉取完消息後立刻就清理消息,而是會保存段文件一段時間,直到其過時再標記爲可清理,由後臺程序按期進行清理。這種機制使得消費者能夠重複消費消息,知足更靈活的需求。

查詢機制

上面說過,kafka雖然做爲消息系統,可是消費消息並非經過推送而是經過拉取來消費的,client須要經過offset和size參數主動去查詢消息。

kafka收到客戶端請求後,對消息的尋址會通過下面幾個步驟:

  1. 查找具體的Log Segment,kafka將段信息緩存在跳躍表中,因此這個步驟將從跳躍表中獲取段信息。
  2. 根據offset在index文件中進行定位,找到匹配範圍的偏移量position,此時獲得的是一個近似起始文件偏移量。
  3. 從Log文件的position位置處開始日後尋找,直到找到offset處的消息。

kafka讀取示意圖:

RabbitMQ vs kafka

介紹了kafka的實現原理,咱們再來對比一下一樣做爲消息隊列服務的RabbitMQMQ的應用也很普遍,功能多而全,那麼和MQ相比,kafka有哪些優點呢?爲何咱們會使用kafka而拋棄了RabbitMQ呢?

RabbitMQ流程圖:

RabbitMQ消費者只能從隊列頭部按序進行消費,消息一旦被消費,就會被打上刪除標記,緊接着消費下一條消息,沒辦法進行回溯操做,這樣的話一個消費者消費完消息,另外一個消費者就別想再消費了。而Kafka提供動態指定消費位點,可以靈活地進行回溯消費操做,只要該消息還在生命週期內能夠重複拉取,而且不一樣消費者能夠互不干擾的消費同一個消息隊列,這就比RabbitMQ靈活多了。

kafka消費位點示意圖:

RabbitMQ若是要知足多個消費者消費同一個消息隊列,也能夠藉助exchange路由能力,可是這樣會將消息複製到多個隊列,每一個消費者須要綁定一個本身的隊列進行消費。若是有幾百個消費者,那麼隊列複製幾百倍,引發mq的消息水位猛漲,容易失控。而kafka就沒這個問題,無論多少個消費者都只須要一個隊列就能知足,每一個消費者均可以完整地不相互干擾地消費隊列中的全部消息。

固然,RabbitMQ也有其優勢,它提供的exchange,binding, queue等抽象實體,提供強大的路由關係(rounte key and bindkey)和消息過濾能力。做爲傳統消息系統提供了細粒度的消息控制能力。而Kafka主要是面向高流量,大吞吐的批處理系統,在路由抽象方面化繁爲簡,重點關注系統的高吞吐,因此使用上更爲簡潔。

kafka還有傳統解決方案沒法知足的高伸縮能力等優點,這裏就不一一介紹了。

Kafka在郵件系統data bus中的運用

正由於kafka有着以上介紹的能力和優點,咱們的郵箱服務中採用了它做爲消息系統,其中一個應用就是郵件系統的data bus。

data bus介紹

郵件系統用戶收發信流程伴隨着大量的業務邏輯和子系統調用,若是將這些流程都強依附在主幹枝上,將會對系統形成較大的壓力,整個業務流程也將變得複雜而緩慢。因此經過數據總線將主次流程進行解耦,減輕收發信主流程的複雜度,使其能夠以更快的速度完成,加快系統響應時間。主流程產生事件源,經過kafka的傳輸,觸發多個次要流程,次要流程能夠併發在系統後臺完成,而且能夠輕易的擴展多種多樣的次要流程。

下圖以簡化後的信流程爲例:

Kafka在data bus中的運用

郵件系統在完成收發信流程後,會生成當次流程相關的系統事件,好比新郵件事件。data bus將這些事件寫入到kafka集羣的相應topic中,下游的一系列子系統對topic進行消費。

  1. 每一個不一樣的流程會對應不用的topic,以區分不一樣類別的事件,好比新進郵件,郵件已讀,郵件刪除等。
  2. 每一個topic能夠根據各自的消息吞吐量和併發需求劃分紅多個partition,好比新進郵件量大能夠劃分紅256個分區,郵件刪除量小則能夠劃分32個分區
  3. 每一個事件按什麼機制來分配到相應的分區呢?通常來講能夠按郵筒來劃分,同一個郵筒的事件進入同一個partition,這樣就保證了同一郵筒發生的事件的順序。
  4. 不一樣事件的時效性可能有不一樣,因此其須要保存的時間也能夠不一樣,能夠根據業務的需求來設置topic的保留時長。
  5. 因爲事件所有寫入到kafka中,後臺任務能夠任意消費,因此能夠靈活地增長不一樣的業務流程。

以下圖所示,應用消費能力能借助Kafka集羣實現彈性擴容

總    結

kafka在郵件系統中的應用給咱們帶來的好處:

  • 時延敏感型業務:經過提升業務Topic的Partition數量,一來留下了較好的機器擴容的空間,另外一方面也能夠經過提升消費者併發線程數來提高應用總體消費速度,減小時延。
  • 慢速型業務:有些不關心時效性的下游業務,在考慮消息生命週期等因素,能夠很好地利用Kafka的消息堆積能力,磁盤存儲能力,削峯填谷,讓消費流速適應本身的處理能力,不至於由於忽然間的大量消息衝擊而崩潰。
相關文章
相關標籤/搜索