所謂的Messaging System就是一組規範,企業利用這組規範在不一樣的系統之間傳遞語義準確對的消息,實現鬆耦合的異步數據傳輸。簡單理解爲系統A將消息發送給Messaging System,系統B從Messaging System中獲取系統A發送的消息。消息系統主要做用能夠歸納爲四個字:削峯填谷。經過消息系統能夠對抗這種上下游消息系統TPS的錯配以及瞬時峯值流量。java
補充一點:數據庫
一般來講,兩個進程進行數據流交互的方式通常有三種:安全
經過數據庫:進程1寫入數據庫;進程2讀取數據庫網絡
經過服務調用:好比REST或RPC,而HTTP協議一般就做爲REST方式的底層通信協議架構
經過消息傳遞的方式:進程1發送消息給名爲broker的中間件,而後進程2從該broker中讀取消息。消息傳輸協議屬於這種模式負載均衡
所以,Messageing System必須保證消息的傳輸格式的語義正確解析無歧義,另外還要對如何傳輸消息進行設計。對於第一點Kafka使用的是純二進制的字節序列,對於第二點消息的傳輸方式大概有兩種:框架
點對點模式:系統A發送的消息只能被系統B所接受,其餘任何系統不能讀取系統A發送的消息運維
發佈(publish)/訂閱(suscribe)模式:能夠存在多個消息發佈者往同一topic中發送數據,同時能夠存在多個消費者對統一topic的數據進行消費。機器學習
kafka同時支持者兩種消息傳輸模式。異步
Kafka既是一個開源的分佈式消息系統,又是一個分佈式流平臺。
kafka在設計之初旨在提供三個方面的特性:
提供一套API實現生產者消費者;
下降網絡傳輸和磁盤存儲開銷
實現高伸縮性架構
從以上三點能夠看出,kafka的設計之初的目的實際上是做爲一個消息系統,主要做用是承接上下游、串聯數據流管道。直到kafka0.10.0.0版本正式推出了流處理組件Kafka Streams,Kafka正式變身爲流處理平臺。那麼kafka streams和其餘大數據流處理框架相比的優點主要表如今:
更容易實現端到端的正確性。實現正確性的基石是要求框架可以提供精確一次性處理語義,即處理一條消息有且只有一次影響系統的狀態。目前主流的大數據流處理框架都宣稱實現了精確一次處理語義,可是有條件的,只能實現框架內的精確一次處理語義,沒法實現端到端的精確一次處理語義。而kafka streams的數據流轉和計算都在kafka內部,所以可以實現端到端的精確一次處理語義。
他本身對於流式計算的定位。官網上明確標識Kafka Streams是一個搭建實時流處理的客戶端庫,而非一個完整的功能系統。所以kafka不提供相似於集羣調度和彈性部署等開箱即用的運維特性,須要本身選擇合適的工具和系統來幫助kafka流處理應用實現此類功能。kafka Streams的定位是中小型公司,數據量沒有那麼大,使用大數據流處理框架有點浪費。
Apache Kafka。
Apache Kafka是社區版kafka。它的優點在於毫無疑問它是開發人數最多、版本迭代最快的Kafka。他的劣勢在於僅僅提供了最基礎的組件,對於Kafka Connect,僅僅提供了一種鏈接器即讀寫磁盤文件的鏈接器,而沒有於其餘系統交互的鏈接器。另外,Apache Kafka也沒有提供任何監控的框架和工具。須要藉助於第三方框架(Kafka Manager、kafka eagle、JMXTrans + InfluxDB + Grafana)
Confluent Kafka
Confluent公司基於Apache Kafka建立的商業版Kafka
CDH/HDP Kafka
Cloudera提供的CDH和HortonWorkers提供的HDP是著名的大數據平臺,裏邊集成了目前主流的大數據處理框架,可以幫助用戶實現從分佈式存儲、集羣調度、流處理到機器學習、實時數據庫等方面的數據處理。CDH和HDP都集成了Apache Kafka。
補充kafka的性能監測工具:
Kafka本身提供了kafka-producer-perf-test和kafka-consumer-perf-test腳本能夠作producer和consumer的性能測試。另外LinkedIn開源了一款名爲kafka-monitor的端到端系統測試工具,也能夠用來測試Kafka集羣end-to-end的性能。有些遺憾的是這個工具幾乎沒什麼人維護了。
kafka屬於分佈式消息系統,它的主要功能室提供一套完備的消息發佈訂閱的解決方案,實現不一樣系統之間的消息傳遞。kafka中發佈訂閱的對象就是topic,能夠將topic理解爲某一類消息的一個標識。
客戶端:向主題發佈消息的客戶端應用程序就稱爲生產者(Producer),訂閱主題的客戶端應用程序稱之爲消費者(Consumer)。生產者、主題和消費者的數量關係不固定,一個生產者能夠不斷的向一個或多個主題發送消息,一個消費者能夠訂閱一個或多個主題。
服務端:kafka的服務端由被稱爲Broker的服務進程組成,給一個kafka集羣由多個broker進程組成。Broker主要負責接收和處理客戶端的請求,以及對消息進行持久化。雖然一臺主機能夠運行多個Broker進程,但更爲常見的作法是將Broker運行在不一樣的主機上,實現容災與高可用。
另一個實現高可用的方式是副本機制(Replication)。副本機制的基本思想就是將相同的數據拷貝到不一樣的機器上。kafka定義了兩類副本:Leader Replia和Follower Replia。Leader主要是接收處理客戶端的請求,Follower主要同步Leader的數據,不能與外界進行交互。
簡單一句話就生產者老是想leader發送數據,而消費者老是從leader消費數據。follower就作一件事,請求leader將最新的消息發動給它。Kafka不能推送消息給consumer。Consumer只能不斷地輪訓去獲取消息。從Kafka流向consumer的惟一方式就是經過poll。另外維持一個長鏈接去輪訓的開銷一般也沒有你想的那麼大,特別是Kafka用的是Linux上的epoll,性能還不錯,至少比select好。
分區中的全部副本統稱爲AR(assigned Replica),很所時候follower副本中的消息相對於leader而言會有必定的滯後,這個滯後範圍是能夠經過參數進行配置的。全部與leader保持必定程度同步(並不必定是徹底同步)的副本組成ISR(In-Sync Replica),剩餘部分爲OSR。因此AR=ISR+OSR。
leader副本負責維護和跟蹤全部follower副本的滯後狀態,當follower副本滯後太多或失效時,leader副本會將它從ISR中剔除,若是OSR中有follower副本追上leader副本,leader副本會將它從OSR遷移至ISR。默認狀況下(可經過參數進行改變),leader副本發生故障,只有ISR集合中的副本纔有資格參與leader的選舉。
副本機制保證了數據的不丟失,提高容災能力,但沒法解決伸縮性問題(Scalability)。所謂的額伸縮性能夠這樣理解。假若一個leader積累了足夠多的數據,致使單臺Broker沒法容納。Kafka的解決方式就是Partition機制,將一個topic的數據劃分爲多個分區,分區是有序的,編號從0開始,生產者生產的某一條數據只會發送到某一個分區,每一條消息在分區上的位置成爲Offset。其實副本機制是創建在分區機制之上的,一個topic向的全部分區都有一個leader和多個folllower。分區在存儲層能夠被看作是一個可追加的日誌文件,消息在追加到分區日誌文件時,會分配一個特定的偏移量。每一條消息發送到broker以前都會根據分區規則選擇存儲到那個具體分區。分區的數量能夠在出題建立的時候指定,也能夠在建立主題完以後進行修改實現水平擴展。
消費者組:多個消費者共同組成一個組來消費一組主題。這個主題的某一個分區只會被消費者的某個特定分區所消費,其餘消費者實例不能進行消費。之因此引入消費者組,更多的是由於多個消費者同時消費能夠提升消費端的TPS。另外這裏的消費者實例能夠是運行消費者的應用進程,也能夠是一個線程。消費者組內的消費者除了瓜分主題消息的功能,還能夠互相協做,當某個消費者掛掉,kafka可以自動檢測掉,進行分區的重平衡(Rebalance )。另外每個消費者在消費過程當中必然會記錄消費到了分區那個位置,成爲消費者偏移量(Consumer Offset)
一張圖簡單歸納一下:
kafka的Broker是如何對消息進行持久化的?
kafka使用消息日誌(Log)來保存數據,一個日誌就是磁盤上一個只支持追加(Append Only)的物理文件,用順序IO代替隨機IO,是kafka實現高吞吐的一個重要手段。不過若是不停地向統一日誌文件追加數據,總會耗盡全部磁盤空間,所以kafka必然會按期的刪除消息,回收磁盤。kafka是經過日誌段(Log Segment)機制進行磁盤迴收的。在kafka的底層一個日誌又進一步分紅多個日誌段,消息被追加到當前最新的日誌段中,當寫滿一個日誌段後,kafka會自動切分出一個新的日誌段,並將老的日誌段封存起來。kafka在後臺會有定時認爲會按期的檢查老的日誌段是夠可以被刪除,從而實現磁盤迴收的目的。
請思考一下爲何 Kafka 不像 MySQL 那樣容許Follower對外提供服務,支持主從讀寫分離?
主從讀寫分離主要目的就是緩解leader節點的壓力,將讀請求負載到多個follower上,提高讀操做的性能。這種設計只是一種架構,無優劣之說,只是有本身的適用場景而已,一般適用於讀多寫少的場景。而對於kafka而言,它是一個消息系統而不是以存儲的方式對外提供讀服務,一般會涉及到頻繁的生產數據和消費數據,並不符合讀多寫少的應用場景。若是Kafka的分區相對均勻地分散到各個broker上,一樣能夠達到負載均衡的效果,不必刻意實現主寫從讀增長代碼實現的複雜程度。
kafka的副本機制採用的是異步消息拉取,所以存在leader和follower的數據一致性問題,若是要實現讀寫分離,必需要處理好副本lag致使的數據一致性問題。
分佈式系統中replica的leader和follower之間如何複製數據保證消息的持久化的問題,我瞭解的是有3種模式:
1.生產者消息發過來之後,寫leader成功後即告知生產者成功,而後異步的將消息同步給其餘follower,這種方式效率最高,但可能丟數據;
2.同步等待全部follower都複製成功後通知生產者消息發送成功,這樣不會丟數據,但效率不高;
3.折中的辦法,同步等待部分follower複製成功,如1個follower複製成功再返回,這樣兼顧效率和消息的持久化。
目前Kafka不支持第三種「折中」辦法。。。要麼只寫leader,要麼全部follower所有同步。可是,我贊成不少分佈式系統是能夠配置同步follower和異步follower共存的,好比一個同步follower+N-1個異步follower的僞同步。Facebook的MySQL就是這個原理。
從官網下載kafka時,會出現以下兩種狀況。可是不管是哪一種狀況,Kafka-2.11-2.2.1,其中2.11指的是scala編譯器的版本。2.2.1纔是kafka的版本。Kafka版本經歷了由四位表示到三位表示的轉變,1.0.0版本以前採起四位,以後採用3位,不管是四位仍是三位,kafka版本構成都是:大版本號(Major version)-小版本號(Minor Version)-修訂版本號(Patch)。