【中间件】大数据之分布式消息队列Kafka
目錄
Kafka設(shè)計(jì)動(dòng)機(jī)
Kafka特點(diǎn)
Kafka設(shè)計(jì)架構(gòu)
基本架構(gòu)
Kafka各組件詳解
Kafka關(guān)鍵技術(shù)點(diǎn)
典型應(yīng)用場(chǎng)景
? ? ? 在大數(shù)據(jù)數(shù)據(jù)收集環(huán)節(jié),需要構(gòu)建數(shù)據(jù)流水線,其中一種方式可以通過消息隊(duì)列實(shí)現(xiàn)。在實(shí)際應(yīng)用中,不同服務(wù)器產(chǎn)生的日志,比如指標(biāo)監(jiān)控?cái)?shù)據(jù),用戶搜索日志,用戶點(diǎn)擊日志等,需要同時(shí)傳送到多個(gè)系統(tǒng)中以便進(jìn)行相應(yīng)的邏輯處理和挖掘。
? ? ? 消息隊(duì)列位于生產(chǎn)者和消費(fèi)者之間的“中間件”,解除了生產(chǎn)者和消費(fèi)者的直接依賴關(guān)系,使得軟件架構(gòu)更容易擴(kuò)展和伸縮;能夠緩沖生產(chǎn)者產(chǎn)生的數(shù)據(jù),防止消費(fèi)者無法及時(shí)處理生產(chǎn)者產(chǎn)生的數(shù)據(jù)。
Kafka設(shè)計(jì)動(dòng)機(jī)
數(shù)據(jù)流水演化隨著業(yè)務(wù)復(fù)雜度和產(chǎn)生數(shù)據(jù)量不斷增加,逐漸演化成上圖數(shù)據(jù)收集模式,并將收集到數(shù)據(jù)直接寫入后端,則會(huì)產(chǎn)生以下幾個(gè)潛在問題:
- 數(shù)據(jù)生產(chǎn)者和消費(fèi)者耦合度過高
- 生產(chǎn)者和消費(fèi)者間數(shù)據(jù)處理速率不對(duì)等
- 大量并發(fā)的網(wǎng)絡(luò)連接對(duì)后端消費(fèi)者不夠友好
為了解決以上問題,引入“中間件”,從這個(gè)角度理解Kafka 如下圖所示(Kafka在數(shù)據(jù)流中扮演的角色):
- 消息中間件:避免生產(chǎn)者和消費(fèi)者直接相互產(chǎn)生的彼此高度依賴,使得兩者中任何一個(gè)由變化,都不會(huì)影響另一方。
- 消息隊(duì)列:緩存生產(chǎn)者產(chǎn)生的數(shù)據(jù),使得消費(fèi)者可以重復(fù)消費(fèi)歷史數(shù)據(jù);平滑生產(chǎn)者產(chǎn)生數(shù)據(jù)速度和消費(fèi)處理數(shù)據(jù)速度的不對(duì)等。
- 發(fā)布訂閱系統(tǒng):消費(fèi)者訂閱某類主題的數(shù)據(jù),當(dāng)生產(chǎn)者產(chǎn)生對(duì)應(yīng)主題的數(shù)據(jù)后,所有訂閱者會(huì)快速獲取到數(shù)據(jù)。隨時(shí)增加新的消費(fèi)者而無需進(jìn)行任何系統(tǒng)層面的修改。
- 消息總線:所有收集到的數(shù)據(jù)會(huì)流經(jīng) Kafka,之后由Kafka分流后,進(jìn)入各個(gè)消費(fèi)者系統(tǒng)。
Kafka特點(diǎn)
Kafka是在大數(shù)據(jù)背景下產(chǎn)生,能應(yīng)對(duì)海量數(shù)據(jù)的處理系統(tǒng)。具有以下特點(diǎn):
- 高性能:相比RabbitMQ等消息隊(duì)列,Kafka 具有更高的性能和吞吐率。
- 良好擴(kuò)展性:采用分布式設(shè)計(jì)架構(gòu),數(shù)據(jù)經(jīng)分片后寫入多個(gè)節(jié)點(diǎn),既可以突破單節(jié)點(diǎn)數(shù)據(jù)存儲(chǔ)和處理的瓶頸,也可以實(shí)現(xiàn)容錯(cuò)等功能。
- 數(shù)據(jù)持久化:數(shù)據(jù)消息均會(huì)持久化到磁盤上,并通過多副本策略避免數(shù)據(jù)丟失,采用順序?qū)?#xff0c;順序讀,和批量寫等機(jī)制,提升磁盤操作的效率。
Kafka設(shè)計(jì)架構(gòu)
1. 基本架構(gòu)
Kafka 架構(gòu)由 Producer,Broker 和 Consumer?三類組件構(gòu)成。
- Producer 將數(shù)據(jù)寫入Broker,Consumer 從 Broker上讀取數(shù)據(jù)進(jìn)行處理,Broker構(gòu)成了連接 Producer?和?Consumer 的“緩沖區(qū)”。
- Broker?和 Cunsumer?通過?Zookeeper?做協(xié)調(diào)和服務(wù)發(fā)現(xiàn)。
- 多個(gè)?Broker?構(gòu)成一個(gè)可靠的分布式消息存儲(chǔ)系統(tǒng),避免數(shù)據(jù)丟失。
- Broker?中的消息被劃分成若干個(gè) topic ,同屬于一個(gè)?topic?的所有數(shù)據(jù)按照某種策略被分成多個(gè)?partition?以實(shí)現(xiàn)負(fù)載分?jǐn)?/strong>和數(shù)據(jù)并行處理。
- 采用 push-pull,即 Producer 將數(shù)據(jù)直接 “push” 給 Broker, 而 Consumer 從Broker?“pull”數(shù)據(jù),這種架構(gòu)優(yōu)勢(shì)帶來以下兩點(diǎn):
- Consumer 可以根據(jù)自己的實(shí)際負(fù)載和需求獲取數(shù)據(jù)(自己主動(dòng)去拉取消息進(jìn)行消費(fèi))
-
Consumer 自己維護(hù)已讀取消息的?offset 而不是由Broker 端維護(hù),大大緩解 Broker 的壓力,使得它更加輕量級(jí)。?
2. Kafka各組件詳解
1.producer
由用戶使用 Kafka 提供的?SDK?開發(fā)的,Producer 將數(shù)據(jù)轉(zhuǎn)化成 “消息”,并通過網(wǎng)絡(luò)發(fā)送給 Broker。每條消息表示為一個(gè)三元組: <topic, key, message>
- topic:表示該條消息所屬的 topic,劃分消息的邏輯概念。一個(gè) topic 可以分布到多個(gè)不同的 Broker 上。
- key:表示該消息的主鍵。根據(jù)主鍵將同一個(gè) topic 下消息劃分成不同的分區(qū) ( partition ),默認(rèn)基于哈希取模算法,用戶可以自行設(shè)置分區(qū)算法。如下圖演示 Producer 寫消息的過程,假設(shè) topic A 共分為 4 個(gè) partition (創(chuàng)建 topic 時(shí)靜態(tài)制定)。
- message:消息值,其類型為字節(jié)數(shù)組,可以是普通字符串,JSON對(duì)象,或者 JSON, Acro,Thrift或Protobuf等序列化框架序列化后的對(duì)象。
2. Broker
主要職責(zé)是接受 Producer 和 Consumer 的請(qǐng)求,并把消息持久化到本地磁盤。Broker一般有多個(gè),組成一個(gè)分布式高容錯(cuò)的集群。
Kafka Broker 集群- Broker 以 topic 為單位將消息分成不同的分區(qū) (partition),每個(gè)分區(qū)可以有多個(gè)副本,通過數(shù)據(jù)冗余的方式實(shí)現(xiàn)容錯(cuò)。當(dāng) partition 存在多個(gè)副本時(shí),其中一個(gè)是 leader,對(duì)外提供讀寫請(qǐng)求,其余均是 follower,僅僅同步 leader 中的數(shù)據(jù),并在 leader 出現(xiàn)問題時(shí),通過選舉算法將其中的某一個(gè)提升為 leader。
- Broker 能夠保證同一個(gè) topic 在同一個(gè) partition 內(nèi)部的消息是有序的,但無法保證 partition 之間的消息全局有序。在實(shí)際應(yīng)用中,合理利用分區(qū)內(nèi)部有序這一特征即可完成時(shí)序相關(guān)的需求。
- Broker 中保存數(shù)據(jù)是有有效期,一旦超過了有效期,對(duì)應(yīng)的數(shù)據(jù)被移除以釋放磁盤空間。在有效期期內(nèi),消息可以重復(fù)讀取而不受限制。
- Broker 以追加的方式將消息寫到磁盤文件中,且每個(gè)分區(qū)中消息被賦予了唯一整數(shù)標(biāo)識(shí),稱之為 “offset” (偏移量)。
- Broker 僅提供基于 offset 的讀取方式 ,不會(huì)維護(hù)各個(gè) Consumer 當(dāng)前已消費(fèi)的 offset 值,而是由?Consumer 各自維護(hù)當(dāng)前讀取的進(jìn)度。Consumer 讀取數(shù)據(jù)時(shí)告訴 Broker 請(qǐng)求消息的起始 offset 值,Broker將之后的消息流式發(fā)送過去。如下圖所示:
3.Consumer
- 主動(dòng)從 Broker 拉取(pull)消息進(jìn)行處理,這個(gè)機(jī)制大大降低了 Broker 的壓力,使得 Broker 吞吐率很高。
- 每個(gè)Consumer 自己維護(hù)最后一個(gè)已讀取消息的 offset,并在下次請(qǐng)求從這個(gè) offset 開始的消息。
- 多個(gè)Consumer 構(gòu)成一個(gè)Consumer Group,共同讀取同一個(gè)?topic?中的數(shù)據(jù),提高數(shù)據(jù)讀取效率。Kafka 可自動(dòng)為同一個(gè)Group 中的 Consumer 分?jǐn)傌?fù)載,從而實(shí)現(xiàn)消息的并發(fā)讀取,在某個(gè)Consumer發(fā)生故障時(shí),自動(dòng)將它處理的 partition 轉(zhuǎn)移給同 Group 中的 Consumer 處理。
4.Zookeeper
在?Kafka 集群中,Zookeeper 擔(dān)任分布式服務(wù)協(xié)調(diào)作用,Broker 和 Consumer 直接依賴于 Zookeeper 才能工作。
- Broker 與 Zookeeper:所有 Broker 會(huì)向 Zookeeper 注冊(cè),將自己的位置,健康狀況,維護(hù)的 topic,partition等信息寫入 Zookeeper ,以便其他 Consumer 可以發(fā)現(xiàn)和獲取這些數(shù)據(jù)。
- Consumer 與 Zookeeper:Consumer Group 通過Zookeeper 保證內(nèi)部各個(gè) Consumer 的負(fù)載均衡,在某個(gè) Consumer 或 Broker 出現(xiàn)故障時(shí),重新分?jǐn)傌?fù)載。Consumer (僅限于 height-level API,如果是 low-level API,用戶需要自己保存和恢復(fù)offset)會(huì)將最近獲取消息的 offset 寫入 Zookeeper,以便出現(xiàn)故障重啟后,能夠接著故障前的斷點(diǎn)繼續(xù)讀取數(shù)據(jù)。
3. Kafka關(guān)鍵技術(shù)點(diǎn)
1. 可控的可靠性級(jí)別
Producer 通過兩種方式向 Broker 發(fā)送數(shù)據(jù):同步 與 異步。異步方式通過批處理的方式,可大大提高數(shù)據(jù)寫入效率。這兩種方式均支持通過控制消息應(yīng)答方式,在寫性能與可靠性之間做一個(gè)較好的權(quán)衡。目前支持三種消息應(yīng)答方式,通過request.required.ack 控制:
- 0:無需對(duì)消息進(jìn)行確認(rèn),性能最高,但不能確保消息被成功接收并寫入磁盤。
- 1:需要等到 leader partition 寫成功后才會(huì)返回,但對(duì)應(yīng)的 follower partition 不一定寫成功。在性能與可靠性之間進(jìn)行折中。
- -1:需要等到所有 partition 均寫成功后才會(huì)返回。性能較低,但可靠性最高。
2. 數(shù)據(jù)多副本
Broker 允許為每個(gè) topic 中的數(shù)據(jù)存放多個(gè)副本,以達(dá)到容錯(cuò)的目的。Kafka 采用強(qiáng)一致的數(shù)據(jù)復(fù)制策略。
Kafka Broker 多副本放置3. 高效的持久化機(jī)制
直接將消息持久化到磁盤而不是內(nèi)存中,這要求必須采用高效的數(shù)據(jù)寫入和存儲(chǔ)方式。Kafka Broker 將收到的數(shù)據(jù)順序寫入磁盤,并結(jié)合基于 offset 的數(shù)據(jù)組織方式,能達(dá)到高效的讀速度和寫速度。
4. 數(shù)據(jù)傳輸優(yōu)化:批處理與zero-copy技術(shù)
為了優(yōu)化 Broker 與 Consumer?之間的網(wǎng)絡(luò)數(shù)據(jù)傳輸效率,Kafka引入了大量?jī)?yōu)化技術(shù),典型的兩個(gè)代表:
- 批處理:發(fā)送是將多條消息進(jìn)行組裝,同時(shí)對(duì)數(shù)據(jù)格式統(tǒng)一設(shè)計(jì),避免數(shù)據(jù)格式轉(zhuǎn)換帶來開銷。
- zero-copy技術(shù):一般情況下,一條存儲(chǔ)在磁盤的數(shù)據(jù)從讀取到發(fā)送出去需要經(jīng)過四次拷貝(內(nèi)核狀態(tài) read buffer? > 用戶態(tài)應(yīng)用程序?buffer? > 內(nèi)核態(tài) socket buffer? > 網(wǎng)卡NIC buffer)和兩次系統(tǒng)調(diào)用。經(jīng)過zero-copy技術(shù)優(yōu)化后,數(shù)據(jù)只需三次拷貝(少了 用戶態(tài)應(yīng)用程序?buffer),且無需使用任何系統(tǒng)調(diào)用,大大提高數(shù)據(jù)發(fā)送效率。如下圖所示:
5. 可控的消息傳遞語(yǔ)義
根據(jù)接受者受到重復(fù)消息的次數(shù),將消息傳遞語(yǔ)義分為三種:
- at most once:不需要等待確認(rèn),消息可能被消費(fèi)者成功接收,也可能丟失。
- at least once:需要等待確認(rèn),如未收到確認(rèn)則會(huì)重發(fā);保障消費(fèi)者收到消息,但可能會(huì)收到多次。
- exactly once:消費(fèi)者會(huì)且只會(huì)處理一次同一條消息。
實(shí)現(xiàn)第三種語(yǔ)義,常用技術(shù)手段有:
- 兩段鎖協(xié)議:分布式中常用的一致性協(xié)議。
- 在支持冪等操作下,使用 at least once 語(yǔ)義。Producer 與 Broker,? Broker 與 Consumer 之間,均存在消息傳遞語(yǔ)義問題。
典型應(yīng)用場(chǎng)景
1. 消息隊(duì)列
與 RabbitMQ 和 ZeroMQ 等開源消息隊(duì)列相比,Kafka 具有高吞吐率,自動(dòng)分區(qū),多副本以及良好容錯(cuò)性等特點(diǎn),使得它非常適合大數(shù)據(jù)應(yīng)用場(chǎng)景。
2. 流式計(jì)算框架的數(shù)據(jù)源
在流式計(jì)算框架,為了保證數(shù)據(jù)不丟失,具備“at least once”數(shù)據(jù)發(fā)送語(yǔ)意,通常在數(shù)據(jù)源中使用具有高性能的消息隊(duì)列。
3. 分布式日志收集系統(tǒng)中Source或Sink
可與日志收集組件 Flume 或 Logstash 組合使用,擔(dān)任 Source 或 Sink 的角色。
4. Lambda Architecture 中的 Source
同時(shí)為批處理和流式處理兩條流水線提供數(shù)據(jù)源
?
注:內(nèi)容主要整理自書本《大數(shù)據(jù)技術(shù)體系詳解 原理、架構(gòu)與實(shí)踐》 董西成
與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的【中间件】大数据之分布式消息队列Kafka的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【项目管理】专用中英文术语词汇 205
- 下一篇: 【科普】一图区分 IAAS + PAAS