一個流平臺通常有三個功能:數據庫
1 發佈和訂閱消息流,相似於消息隊列或者專業的消息系統。服務器
2 以容錯持久的方式存儲消息流。負載均衡
3 處理接收到的消息流。分佈式
Kafka通常普遍用於兩類應用:函數
1 創建能夠在系統或應用之間穩定獲取數據的實時流數據通道。工具
2 創建轉換貨響應數據流的實時流應用。性能
爲了搞清楚Kafka是怎麼作到這些的,讓咱們自底向上的深刻探索Kafka這些能力。測試
開始是一些概念:spa
1 Kafka是運行在能夠擴展的多個數據中心集羣上命令行
2 Kafka集羣存儲了稱爲topics的分類流數據
3 每條記錄都包含了key,value和時間戳
Kafka有四個核心的API:
Producer API容許應用發佈流記錄到一個或更多的Kafka主題上。
Consumer API容許應用訂閱到一個或更多的主題上並處理其上的流記錄。
Streams API容許應用做爲流處理者,從一個或更多的主題上消費而且生產輸出流到一個或更多的輸出主題上,高效地傳遞輸入流到輸出流。
Connector API容許創建和運行可重用生產者或消費者,鏈接Kafka主題到已有的應用或數據系統中。好比,鏈接到關係型數據庫上的connector可能捕捉到每一個來自表的變化。
在Kafka中,客戶端和服務端的通訊是簡易,高可用,對語言不敏感的TCP協議。協議是分版本的而且向下兼容。咱們不只提供Kafka的Java客戶端,還支持其餘不少語言。
讓咱們先來看下Kafka爲流記錄提供的核心抽象的組件——topic
topic是記錄發佈的分類或飼養者。在Kafka中的topics老是多個訂閱,意思是說topic能夠沒有,或者有一個或許多個消費者來訂閱寫入其中的數據。
對於每一個topic來說,Kafka集羣保留了一個分區日誌以下圖:
每一個分區是一個有序的,不可變的向一個結構化的提交日誌中持續寫入記錄的序列。在分區中的記錄都被記做一串叫作offset的惟一標識的數字串。
Kafka集羣持久化全部的發佈的記錄——無論他們是否是消費了——食用一個可配置的保留時間。舉個例子,若是保留測試是兩天,那麼在記錄發佈以後的兩天,它能夠被重複消費,在這以後它將會被丟棄來節省空間。Kafka的性能相對於數據大小來講是有效的,因此長期存儲數據不是問題。
事實上,只有保存在每一個消費者上的元數據會在日誌中成爲offset或者消費者位置。offset(偏移)被消費者控制:通常消費者都會在讀取記錄的同時設置offset,可是,實際上,既然位置被消費者控制了那麼消費者就能夠按照順序消費。好比一個消費者能夠重置一個較早時間的offset去響應以前的記錄或者跳轉到最近的記錄並從「如今」開始消費。
這樣的特性意味着Kafka消費者是很是廉價的——他們能夠不用受到集羣或者其餘消費者的影響。好比,他們可使用命令行工具來「tail」任意topic的內容而無需改變已存在的消費者的消費內容。
日誌中的分區有多種用途。首先,它們容許日誌擴展到一個適合於單個服務器的大小。每一個單獨的分區必須適合承載它的服務器,可是一個topic能夠有許多分區,所以能夠處理任意數量的數據。其次,它們做爲一個並行的單元——在這點上能夠作到更多的事情。
日誌分區是分佈在Kafka集羣中的每一個服務器上,用來處理數據和共享分區的請求。每一個分區經過一個可配置的容錯機制的服務器的拷貝。
每一個分區都有一個扮演這「leader」角色和多個(或無)扮演者「followers」角色的服務器。Leader處理全部的讀和寫請求,follwers被動地複製leader上的請求。若是leader發生宕機,一個follower會自動成爲新的leader。每一個leader服務器充當它所在分區的leader或者其餘分區的follower,所以集羣內的負載均衡很好。
Kafka鏡像爲它的集羣提供geo-replication支持。經過景象,消息在多個數據中心或雲中複製。你能夠用在主動或被動的環境下備份或還原;或者覆蓋鄰近你的用戶的數據,或者支持本地數據需求。
生產者根據本身的選擇發佈數據到topics上。生產者有權選擇將記錄發佈到topic中的哪一個分區上。這能夠以輪詢的方式簡單的均衡負載或者根據一些語義上的分區函數(基於記錄中的一些key)。因爲秒級的建分區而被普遍使用。
消費者把它們本身標記爲消費者組名字,每一個發佈到topic上的記錄都會被傳送到消費者組中一個消費者實例。消費者實例能夠在不一樣的進程或不一樣的機器上。
若是全部的消費者實例都在一個消費者組中,記錄就會在消費者實例中實現高效的負載均衡。
若是全部的消費者實例在不一樣的消費者組中,則每一個記錄都會被廣播到全部的消費者進程中。
一個包含兩個Kafka服務器的集羣使用了四個分區(P0-P3)和兩個消費者組。消費者組A有兩個消費者實例,消費者組B有四個。
更通常的是,你的topic擁有很少的consumer groups,每個都充當「邏輯上的訂閱者「。每一個group都由不少消費者實例組成以便擴展和容錯考慮。黨消費者集羣代替了單個進程的時候發佈-訂閱語義是再好不過的了。
在Kafka中實現消費的方法是將日誌中的分區劃分到消費者實例中,這樣每一個實例在任什麼時候間點都是分區的「公平份額」的獨佔使用者。保持組裏成員的地位是由Kafka的協議動態處理的。若是新實例加入了組它們會接管其餘組成員的一些分區;若是一個實例死掉,他的分區就會分配給存在的實例。
Kafka只在一個分區中提供一個總體上有序的記錄,而不會在topic的不一樣分區上存有這些記錄。每一個分區排序經過key和分區數據的能力結合對於大多數應用來講已經足夠了。然而,若是你須要一個來自topic上惟一一個分區上總體上有序的記錄,那麼每一個消費者組只有一個消費者進程。