Kafka是當(dāng)前分布式系統(tǒng)中最流行的消息中間件之一,憑借著其高吞吐量的設(shè)計,,在日志收集系統(tǒng)和消息系統(tǒng)的應(yīng)用場景中深得開發(fā)者喜愛,。本篇就聊聊Kafka相關(guān)的一些知識點。主要包括以下內(nèi)容: Kafka簡介 Kafka特點 Kafka基本概念 Kafka架構(gòu)
Kafka的幾個核心概念 分區(qū)Partition 復(fù)制Replication 消息發(fā)送 消費者組 消費偏移量
Kafka的工程應(yīng)用
Kafka簡介Kafka特點Kafka是最初由Linkedin公司開發(fā),,是一個分布式,、分區(qū)的、多副本的,、多訂閱者,,基于zookeeper協(xié)調(diào)的分布式日志系統(tǒng)(也可以當(dāng)做MQ系統(tǒng)),常見可以用于web/nginx日志,、訪問日志,,消息服務(wù)等等,Linkedin于2010年貢獻(xiàn)給了Apache基金會并成為頂級開源項目,。相比于其他的消息隊列中間件,,Kafka的主要設(shè)計目標(biāo),也即其特點如下: 以時間復(fù)雜度為O(1)的方式提供消息持久化能力,,即使對TB級以上數(shù)據(jù)也能保證常數(shù)時間的訪問性能,。 高吞吐率。即使在非常廉價的商用機(jī)器上也能做到單機(jī)支持每秒100K條消息的傳輸,。 支持Kafka Server間的消息分區(qū),,及分布式消費,,同時保證每個partition內(nèi)的消息順序傳輸。 同時支持離線數(shù)據(jù)處理和實時數(shù)據(jù)處理,。 Scale out:支持在線水平擴(kuò)展
Kafka基本概念Broker Kaka集群中的一臺或多臺服務(wù)器稱為Broker,。Broker存儲Topic的數(shù)據(jù)。 如果某topic有N個partition,,集群有N個broker,,那么每個broker存儲該topic的一個partition。 如果某topic有N個partition,,集群有(N+M)個broker,,那么其中有N個broker存儲該topic的一個partition,剩下的M個broker不存儲該topic的partition數(shù)據(jù),。 如果某topic有N個partition,,集群中broker數(shù)目少于N個,那么一個broker存儲該topic的一個或多個partition,。在實際生產(chǎn)環(huán)境中,,盡量避免這種情況的發(fā)生,這種情況容易導(dǎo)致Kafka集群數(shù)據(jù)不均衡,。
Topic 發(fā)布到Kafka的每條消息都有一個類別,,是個邏輯概念。 物理上不同Topic的消息分開存儲,,邏輯上一個Topic的消息雖然保存于一個或多個broker上,,但用戶只需指定消息的Topic即可生產(chǎn)或消費數(shù)據(jù)而不必關(guān)心數(shù)據(jù)存于何處
Partition 物理上的Topic分區(qū),一個Topic可以分為多個Partition,,至少有一個Partition,。 每個Partition中的數(shù)據(jù)使用多個segment文件存儲,每個Partition都是一個有序的隊列,,不同Partition間的數(shù)據(jù)是無序的,。 Partition中的每條消息都會被分配一個有序的ID(即offset)。
Producer 消息和數(shù)據(jù)的生產(chǎn)者,。Producer將消息發(fā)布到Kafka的topic中,。 Broker接收到Producer發(fā)布的消息后,Broker將該消息追加到當(dāng)前用于追加數(shù)據(jù)的segment文件中,。 Producer發(fā)送的消息,,存儲到一個Partition中,Producer也可以指定數(shù)據(jù)存儲的Partition,。
Consumer Consumer Group 每個消費者都屬于一個特定的消費者組,。 可為每個Consumer指定group name,,若不指定group name則屬于默認(rèn)的group。 一個Topic可以有多個消費者組,,Topic的消息會被復(fù)制到所有的消費者組中,,但每個消費者組只會把消息發(fā)送給該組中的一個消費者。 消費者組是Kafka用來實現(xiàn)一個Topic消息的廣播和單播的手段,。
Leader 每個Partition有多個副本,,其中有且僅有一個作為leader。 Leader是當(dāng)前負(fù)責(zé)數(shù)據(jù)的讀寫的Partition,。
Follower Follower跟隨Leader,,所有寫請求都通過Leader路由,數(shù)據(jù)變更會廣播給所有Follower,,F(xiàn)ollower與Leader保持?jǐn)?shù)據(jù)同步,。 如果Leader失效,則從Follower中選舉出一個新的Leader,。 如果Follower與Leader掛掉、卡住或同步太慢,,Leader會把這個Follower從"in sync replicas"## 高吞吐量的分布式消息組件Kafka是如何工作的
Kafka是當(dāng)前分布式系統(tǒng)中最流行的消息中間件之一,,憑借著其高吞吐量的設(shè)計,在日志收集系統(tǒng)和消息系統(tǒng)的應(yīng)用場景中深得開發(fā)者喜愛,。本篇就聊聊Kafka相關(guān)的一些知識點,。主要包括以下內(nèi)容: Kafka簡介 Kafka特點 Kafka基本概念 Kafka架構(gòu)
Kafka的幾個核心概念 分區(qū)Partition 復(fù)制Replication 消息發(fā)送 消費者組 消費偏移量
Kafka的工程應(yīng)用
Kafka簡介Kafka特點Kafka是最初由Linkedin公司開發(fā),是一個分布式,、分區(qū)的,、多副本的、多訂閱者,,基于zookeeper協(xié)調(diào)的分布式日志系統(tǒng)(也可以當(dāng)做MQ系統(tǒng)),,常見可以用于web/nginx日志、訪問日志,,消息服務(wù)等等,,Linkedin于2010年貢獻(xiàn)給了Apache基金會并成為頂級開源項目。相比于其他的消息隊列中間件,,Kafka的主要設(shè)計目標(biāo),,也即其特點如下: 以時間復(fù)雜度為O(1)的方式提供消息持久化能力,即使對TB級以上數(shù)據(jù)也能保證常數(shù)時間的訪問性能,。 高吞吐率,。即使在非常廉價的商用機(jī)器上也能做到單機(jī)支持每秒100K條消息的傳輸。 支持Kafka Server間的消息分區(qū),及分布式消費,,同時保證每個partition內(nèi)的消息順序傳輸,。 同時支持離線數(shù)據(jù)處理和實時數(shù)據(jù)處理。 Scale out:支持在線水平擴(kuò)展
Kafka基本概念Broker Kaka集群中的一臺或多臺服務(wù)器稱為Broker,。Broker存儲Topic的數(shù)據(jù),。 如果某topic有N個partition,集群有N個broker,,那么每個broker存儲該topic的一個partition,。 如果某topic有N個partition,集群有(N+M)個broker,,那么其中有N個broker存儲該topic的一個partition,,剩下的M個broker不存儲該topic的partition數(shù)據(jù)。 如果某topic有N個partition,,集群中broker數(shù)目少于N個,,那么一個broker存儲該topic的一個或多個partition。在實際生產(chǎn)環(huán)境中,,盡量避免這種情況的發(fā)生,,這種情況容易導(dǎo)致Kafka集群數(shù)據(jù)不均衡。
Topic 發(fā)布到Kafka的每條消息都有一個類別,,是個邏輯概念,。 物理上不同Topic的消息分開存儲,邏輯上一個Topic的消息雖然保存于一個或多個broker上,,但用戶只需指定消息的Topic即可生產(chǎn)或消費數(shù)據(jù)而不必關(guān)心數(shù)據(jù)存于何處
Partition 物理上的Topic分區(qū),,一個Topic可以分為多個Partition,至少有一個Partition,。 每個Partition中的數(shù)據(jù)使用多個segment文件存儲,,每個Partition都是一個有序的隊列,不同Partition間的數(shù)據(jù)是無序的,。 Partition中的每條消息都會被分配一個有序的ID(即offset),。
Producer 消息和數(shù)據(jù)的生產(chǎn)者。Producer將消息發(fā)布到Kafka的topic中,。 Broker接收到Producer發(fā)布的消息后,,Broker將該消息追加到當(dāng)前用于追加數(shù)據(jù)的segment文件中。 Producer發(fā)送的消息,,存儲到一個Partition中,,Producer也可以指定數(shù)據(jù)存儲的Partition。
Consumer 消息和數(shù)據(jù)的消費者,。Consumer從Broker中讀取數(shù)據(jù),。 Consumer可以消費多個topic中的數(shù)據(jù)。
Consumer Group 每個消費者都屬于一個特定的消費者組。 可為每個Consumer指定group name,,若不指定group name則屬于默認(rèn)的group,。 一個Topic可以有多個消費者組,Topic的消息會被復(fù)制到所有的消費者組中,,但每個消費者組只會把消息發(fā)送給該組中的一個消費者,。 消費者組是Kafka用來實現(xiàn)一個Topic消息的廣播和單播的手段。
Leader 每個Partition有多個副本,,其中有且僅有一個作為leader,。 Leader是當(dāng)前負(fù)責(zé)數(shù)據(jù)的讀寫的Partition。
Follower Follower跟隨Leader,,所有寫請求都通過Leader路由,,數(shù)據(jù)變更會廣播給所有Follower,F(xiàn)ollower與Leader保持?jǐn)?shù)據(jù)同步,。 如果Leader失效,,則從Follower中選舉出一個新的Leader。 如果Follower與Leader掛掉,、卡住或同步太慢,,Leader會把這個Follower從"in sync replicas"列表中刪除,重新創(chuàng)建一個Follower,。
Kafka架構(gòu)Kafka一般以集群方式來部署,,一個典型的Kafka集群架構(gòu)如下圖所示: Kafka的幾個核心概念分區(qū)Partition分區(qū)的幾個特點 分區(qū)是Kafka的基本存儲單元,在一個Topic中會有一個或多個Partition,,不同的Partition可位于不同的服務(wù)器節(jié)點上,,物理上一個Partition對應(yīng)于一個文件夾,。 Partition內(nèi)包含一個或多個Segment,,每個Segment又包含一個數(shù)據(jù)文件和一個與之對應(yīng)的索引文件。 對于寫操作,,每次只會寫Partition內(nèi)的一個Segment,;對于讀操作,也只會順序讀取同一個Partition內(nèi)的不同Segment,。 邏輯上,,可以把Partition當(dāng)做一個非常長的數(shù)組,使用時通過這個數(shù)組的索引(offset)訪問數(shù)據(jù),。
高吞吐量設(shè)計分區(qū)正是Kafka高吞吐量設(shè)計的方法之一,,具體體現(xiàn)在這樣幾點: 由于不同的Partition可位于不同的機(jī)器上,因此可以實現(xiàn)機(jī)器間的并行處理,。 由于一個Partition對應(yīng)一個文件夾,,多個Partition也可位于同一臺服務(wù)器上,這樣就可以在同一臺服務(wù)器上使不同的Partition對應(yīng)不同的磁盤,實現(xiàn)磁盤間的并行處理,。 故一般通過增加Partition的數(shù)量來提高系統(tǒng)的并行吞吐量,,但也會增加輕微的延遲。
但以下這幾種情況需要注意: 當(dāng)一個Topic有多個消費者時,,一個消息只會被一個消費者組里的一個消費者消費,; 由于消息是以Partition為單位分配的,在不考慮Rebalance時,,同一個Partition的數(shù)據(jù)只會被一個消費者消費,,所以如果消費者的數(shù)量多于Partition的數(shù)量,就會存在部分消費者不能消費該Topic的情況,,此時再增加消費者并不能提高系統(tǒng)的吞吐量,; 在生產(chǎn)者和Broker的角度,對不同Partition的寫操作是完全并行的,,可是對于消費者其并發(fā)數(shù)則取決于Partition的數(shù)量,。實際中配置的Partition數(shù)量需要根據(jù)所設(shè)計的系統(tǒng)吞吐量來推算。
復(fù)制復(fù)制原理Kafka利用zookeeper來維護(hù)集群成員的信息,,每個Broker實例都會被設(shè)置一個唯一的標(biāo)識符,,Broker在啟動時會通過創(chuàng)建臨時節(jié)點的方式把自己的唯一標(biāo)識注冊到zookeeper中,Kafka中的其他組件會監(jiān)視Zookeeper里的/broker/ids路徑,,所以當(dāng)集群中有Broker加入或退出時,,其他組件就會收到通知。集群間數(shù)據(jù)的復(fù)制機(jī)制,,在Kafka中是通過Zookeeper提供的leader選舉方式實現(xiàn)數(shù)據(jù)復(fù)制方案,。基本原理是:首先選舉出一個leader,,其他副本作為Follower,,所有的寫操作都先發(fā)給leader,然后再由leader把消息發(fā)給Follower,。復(fù)制功能是Kafka架構(gòu)的核心之一,,因為它可以在個別節(jié)點不可用時還能保證Kafka整體的可用性。Kafka中的復(fù)制操作也是針對分區(qū)的,。一個分區(qū)有多個副本,,副本被保存在Broker上,每個Broker都可以保存上千個屬于不同Topic和分區(qū)的副本,。副本有兩種類型: leader副本:每個分區(qū)都會有,,所有生產(chǎn)者和消費者的請求都會經(jīng)過leader; follower副本:不處理客戶端的請求,,它的職責(zé)是從leader處復(fù)制消息數(shù)據(jù),,使自己和leader的狀態(tài)保持一致,; 如果leader節(jié)點宕機(jī),那么某個follower就會被選為leader繼續(xù)對外提供服務(wù),; 復(fù)制因子:一個分區(qū)有幾個副本,。
消息發(fā)送方式從生產(chǎn)者的角度來看,消息發(fā)送到Broker有三種方式: 立即發(fā)送:只發(fā)送消息,,不關(guān)心消息發(fā)送的結(jié)果,。本質(zhì)上也是一種異步發(fā)送的方式,消息先存儲在緩沖區(qū)中,,達(dá)到設(shè)定條件后批量發(fā)送,。當(dāng)然這是kafka吞吐量最高的一種方式,并配合參數(shù)acks=0,這樣生產(chǎn)者不需要等待服務(wù)器的響應(yīng),,以網(wǎng)絡(luò)能支持的最大速度發(fā)送消息,。但是也是消息最不可靠的一種方式,因為對于發(fā)送失敗的消息沒有做任何處理,。 同步發(fā)送:生產(chǎn)者發(fā)送消息后獲取返回的Future對象,,根據(jù)該對象的結(jié)果查看發(fā)送是否成功。如果業(yè)務(wù)要求消息必須是按順序發(fā)送的,,那么可以使用同步的方式,,并且只能在一個partation上,結(jié)合參數(shù)設(shè)置retries的值讓發(fā)送失敗時重試,,設(shè)置max_in_flight_requests_per_connection=1,,可以控制生產(chǎn)者在收到服務(wù)器晌應(yīng)之前只能發(fā)送1個消息,在消息發(fā)送成功后立刻flush,,從而控制消息順序發(fā)送,。 異步發(fā)送:生產(chǎn)者發(fā)送消息時將注冊的回調(diào)函數(shù)作為入?yún)魅耄a(chǎn)者接收到Kafka服務(wù)器的響應(yīng)時會觸發(fā)執(zhí)行回調(diào)函數(shù),。如果業(yè)務(wù)需要知道消息發(fā)送是否成功,,并且對消息的順序不關(guān)心,那么可以用異步+回調(diào)的方式來發(fā)送消息,,配合參數(shù)retries=0,,并將發(fā)送失敗的消息記錄到日志文件中,。
消息發(fā)送確認(rèn)消息發(fā)送到Broker后怎么算投遞成功呢,,Kafka有三種確認(rèn)模式: 三種模式對比的話,性能依次降低,,但可靠性依次提高,。 消息重發(fā)機(jī)制當(dāng)從Broker接收到的是臨時可恢復(fù)的異常時,,生產(chǎn)者會向Broker重發(fā)消息,重發(fā)次數(shù)的限制值由初始化生產(chǎn)者對象的retries屬性決定,,在默認(rèn)情況下生產(chǎn)者會在重試后等待100ms,,可以通過retry.backoff.ms屬性進(jìn)行修改。 批次發(fā)送當(dāng)有多條消息要被發(fā)送到同一個分區(qū)時,,生產(chǎn)者會把它們放到同一個批次里,,Kafka通過批次的概念來提高吞吐量,但同時也會增加延遲,。對批次的控制主要通過構(gòu)建生產(chǎn)者對象時的兩個屬性來實現(xiàn): batch.size:當(dāng)發(fā)往每個分區(qū)的緩存消息數(shù)量達(dá)到這個數(shù)值時,,就會觸發(fā)一次網(wǎng)絡(luò)請求,批次里的所有消息都會被發(fā)送出去,; linger.ms:每條消息在緩存中的最長時間,,如果超過這個時間就會忽略batch.size的限制,由客戶端立即把消息發(fā)送出去,。
消費者組消費者組是Kafka提供的可擴(kuò)展且具有容錯性的消費機(jī)制,,在一個消費者組內(nèi)可以有多個消費者,它們共享一個唯一標(biāo)識,,即分組ID,。組內(nèi)的所有消費者協(xié)調(diào)消費它們訂閱的主題下的所有分區(qū)的消息,但一個分區(qū)只能由同一個消費者組里的一個消費者來消費,。 廣播和單播一個Topic可以有多個消費者組,,Topic的消息會被復(fù)制到所有的消費者組中,但每個消費者組只會把消息發(fā)送給一個消費者組里的某一個消費者,。如果要實現(xiàn)廣播,,只需為每個消費者都分配一個單獨的消費者組接口如果要實現(xiàn)單播,則需要把所有的消費者都設(shè)置在同一個消費者組里 再均衡消費者組里有新消費者加入或者有消費者離開,,分區(qū)所有權(quán)會從一個消費者轉(zhuǎn)移到另一個消費者再均衡協(xié)議規(guī)定了一個消費者組下的所有消費者如何達(dá)成一致來分配主題下的每個分區(qū)觸發(fā)再均衡的場景有三種: 消費偏移量Kafka中有一個叫作_consumer_offset特殊主題用來保存消息在每個分區(qū)的偏移量,,消費者每次消費時都會往這個主題中發(fā)送消息,消息包含每個分區(qū)的偏移量,。如果消費者一直處于運(yùn)行狀態(tài),,偏移量沒什么作用;如果消費者崩潰或者有新的消費者加入消費者組從而觸發(fā)再均衡操作,,再均衡之后該分區(qū)的消費者若不是之前的那個,,提交偏移量就有用了。維護(hù)消息偏移量對于避免消息被重復(fù)消費和遺漏消費,,確保消息的ExactlyOnce至關(guān)重要,,以下是不同的提交偏移量的方式: 自動提交:Kafka默認(rèn)會定期自動提交偏移量,提交的時間間隔默認(rèn)是5秒,。此方式會產(chǎn)生重復(fù)處理消息的問題,; 手動提交:在進(jìn)行手動提交之前需要先關(guān)閉消費者的自動提交配置,,然后用commitSync方法來提交偏移量。處理完記錄后由開發(fā)者確保調(diào)用了commitSync方法,,來減少重復(fù)處理消息的數(shù)量,,但可能降低消費者的吞吐量; 異步提交:使用commitASync方法來提交最后一個偏移量,。消費者只管發(fā)送提交請求,,而不需要等待Broker的立即回應(yīng)。
Kafka的工程應(yīng)用Kafka主要用于三種場景: 基于Kafka的用戶行為數(shù)據(jù)采集要獲取必要的數(shù)據(jù)進(jìn)行用戶行為等的分析,,需要這樣幾個步驟: 前端數(shù)據(jù)(埋點)上報 接收前端數(shù)據(jù)請求 后端通過Kafka消費消息,,必要時落庫 分析用戶行為
基于Kafka的日志收集各個應(yīng)用系統(tǒng)在輸出日志時利用高吞吐量的Kafka作為數(shù)據(jù)緩沖平臺,將日志統(tǒng)一輸出到Kafka,,再通過Kafka以統(tǒng)一接口服務(wù)的方式開放給各種消費者,。做統(tǒng)一日志平臺的方案,收集重要系統(tǒng)的日志集中到Kafka中,,然后再導(dǎo)入ElasticSearch,、HDFS、Storm等具體日志數(shù)據(jù)的消費者中,,用于進(jìn)行實時搜索分析,、離線統(tǒng)計、數(shù)據(jù)備份,、大數(shù)據(jù)分析等,。 基于Kafka的流量削峰為了讓系統(tǒng)在大流量場景下仍然可用,可以在系統(tǒng)中的重點業(yè)務(wù)環(huán)節(jié)加入消息隊列作為消息流的緩沖,,從而避免短時間內(nèi)產(chǎn)生的高流量帶來的壓垮整個應(yīng)用的問題,。
|