kafka 初识
引言
Kafka 起初是 由 LinkedIn 公司采用 Scala 語言開發(fā)的一個(gè) 多分區(qū)、多副本且基于 ZooKeeper 協(xié)調(diào) 的分布式消息系統(tǒng),現(xiàn)已被捐獻(xiàn)給 Apache 基金會(huì)。目前 Kafka 已經(jīng)定位為一個(gè) 分布式流式處理平臺(tái),它以 高吞吐、可持久化 、可水平擴(kuò)展、支持流數(shù)據(jù)處理 等多種特性而被廣泛使用。目前越來越多的開源分布式處理系統(tǒng)如 Cloudera、Storm、Spark、Flink 等都支持與 Kafka 集成。
kafka 應(yīng)用面
目前 kafka 在企業(yè)應(yīng)用中主要體現(xiàn)在三塊:消息系統(tǒng),存儲(chǔ)系統(tǒng),流式處理平臺(tái);其中,消息系統(tǒng)和流式處理平臺(tái)應(yīng)用最為廣泛。
消息系統(tǒng)
Kafka 和其他消息中間件(RabbitMQ,RocketMQ......)都具備 系統(tǒng)解耦、異步通信、流量削峰、 緩沖、冗余存儲(chǔ)、擴(kuò)展性、可恢復(fù)性等功能。與此同時(shí),Kafka 還提供了大多數(shù)消息系統(tǒng)難以實(shí)現(xiàn)的 消息順序性保障 及 回溯消費(fèi)的功能 。
存儲(chǔ)系統(tǒng)
Kafka 把消息持久化到磁盤,相比于其他基于內(nèi)存存儲(chǔ)的系統(tǒng)而言,有效地降低了數(shù)據(jù)丟失的風(fēng)險(xiǎn)。也正是得益于 Kafka 的 消息持久化功能 和 多副本機(jī)制 ,我們可以把 Kafka 作為長(zhǎng)期的數(shù)據(jù)存儲(chǔ)系統(tǒng)來使用,只需要把對(duì)應(yīng)的數(shù)據(jù)保留策略設(shè)置為“永久”或啟用主題的日志壓縮功能即可。
流式處理平臺(tái)
Kafka 不僅為每個(gè)流行的流式處理框架提供了可靠的數(shù)據(jù)來源,還提供了一個(gè)完整的流式處理類庫,比如窗口、連接、變換和聚合等各類操作。
kafka 基本組成
一個(gè)典型的 Kafka 體系架構(gòu)包括 若干 Producer、若干 Broker、若干 Consumer,以及一個(gè) ZooKeeper 集群,如下圖所示。
其中各個(gè)組成部分的作用分別是:
Zookeeper
ZooKeeper 是 Kafka 用來負(fù)責(zé) 集群元數(shù)據(jù)的管理、控制器的選舉 等操作的。
Producer
Producer 負(fù)責(zé)創(chuàng)建消息,然后將消息發(fā)送到 Broker。
Broker
Broker 負(fù)責(zé)將收到的消息存儲(chǔ)到磁盤中。對(duì)于 Kafka 而言,Broker 可以簡(jiǎn)單地看作一個(gè)獨(dú)立的 Kafka 服務(wù)節(jié)點(diǎn)或者是一個(gè) kafka 服務(wù)。一個(gè)或多個(gè) Broker 組成了一個(gè) Kafka 集群。
Consumer
Consumer 負(fù)責(zé)從 Broker 訂閱并消費(fèi)消息。
整個(gè) Kafka 體系結(jié)構(gòu)中除了上面描述的幾個(gè)組成部分之外,還有兩個(gè)特別重要的概念— 主題(Topic) 與 分區(qū)(Partition) 。Kafka 中的消息以主題為單位進(jìn)行歸類,生產(chǎn)者負(fù)責(zé)將消息發(fā)送到特定的主題(發(fā)送到 Kafka 集群中的每一條消息都要指定一個(gè)主題),而消費(fèi)者負(fù)責(zé)訂閱主題并進(jìn)行消費(fèi)。
Topic & Partition
1、 主題是一個(gè)邏輯上的概念,它還可以細(xì)分為多個(gè)分區(qū),一個(gè)分區(qū)只屬于單個(gè)主題。
2、 同一主題下的不同分區(qū)包含的消息是不同的,分區(qū)在存儲(chǔ)層面可以看作一個(gè) 可追加的日志(Log)文件,消息在被追加到分區(qū)日志文件的時(shí)候都會(huì)分配一個(gè)特定的偏移量(offset)。
3、 offset 是消息在分區(qū)中的唯一標(biāo)識(shí),Kafka 通過它來保證消息在分區(qū)內(nèi)的順序性,不過 offset 并不跨越分區(qū),也就是說, Kafka 保證的是分區(qū)有序 而不是主題有序。
如上圖所示,主題中有 4 個(gè)分區(qū),消息被順序追加到每個(gè)分區(qū)日志文件的尾部。Kafka 中的分區(qū)可以分布在不同的服務(wù)器(broker) 上,也就是說,一個(gè)主題可以橫跨多個(gè) broker ,以此來提供比單個(gè) broker 更強(qiáng)大的性能。
每一條消息被發(fā)送到 broker 之前,會(huì)根據(jù)分區(qū)規(guī)則選擇存儲(chǔ)到哪個(gè)具體的分區(qū)。如果分區(qū)規(guī)則設(shè)定得合理,所有的消息都可以均勻地分配到不同的分區(qū)中。如果一個(gè)主題只對(duì)應(yīng)一個(gè)文件,那么這個(gè)文件所在的機(jī)器 I/O 將會(huì)成為這個(gè)主題的性能瓶頸,而分區(qū)解決了這個(gè)問題。在創(chuàng)建主題的時(shí)候可以通過指定的參數(shù)來設(shè)置分區(qū)的個(gè)數(shù),當(dāng)然也可以在主題創(chuàng)建完成之后去修改分區(qū)的數(shù)量,通過增加分區(qū)的數(shù)量可以實(shí)現(xiàn)水平擴(kuò)展。
Partition 的多副本機(jī)制
Kafka 為分區(qū)引入了多副本(Replica)機(jī)制,通過增加副本數(shù)量可以提升容災(zāi)能力。
同一分區(qū)的不同副本中保存的是相同的消息(在同一時(shí)刻,副本之間并非完全一樣),副本之間是 “一主多從” 的關(guān)系,其中 leader 副本負(fù)責(zé)處理讀寫請(qǐng)求,follower 副本只負(fù)責(zé)與 leader 副本的消息同步。副本處于不同的 broker 中,當(dāng) leader 副本出現(xiàn)故障時(shí),從 follower 副本中重新選舉新的 leader 副本對(duì)外提供服務(wù)。Kafka 通過多副本機(jī)制實(shí)現(xiàn)了故障的自動(dòng)轉(zhuǎn)移,當(dāng) Kafka 集群中某個(gè) broker 失效時(shí)仍然能保證服務(wù)可用。
如上圖所示,Kafka 集群中有 4 個(gè) broker,某個(gè)主題中有 3 個(gè)分區(qū),且副本因子(即副本個(gè)數(shù))也為 3,如此每個(gè)分區(qū)便有 1 個(gè) leader 副本和 2 個(gè) follower 副本。生產(chǎn)者和消費(fèi)者只與 leader 副本進(jìn)行交互,而 follower 副本只負(fù)責(zé)消息的同步,很多時(shí)候 follower 副本中的消息相對(duì) leader 副本而言會(huì)有一定的滯后。
kafka 消費(fèi)端的容災(zāi)能力
Kafka 消費(fèi)端也具備一定的容災(zāi)能力。Consumer 使用拉(Pull)模式從服務(wù)端拉取消息,并且保存消費(fèi)的具體位置,當(dāng)消費(fèi)者宕機(jī)后恢復(fù)上線時(shí)可以根據(jù)之前保存的消費(fèi)位置重新拉取需要的消息進(jìn)行消費(fèi),這樣就不會(huì)造成消息丟失。
分區(qū)的副本種類
分區(qū)中的所有副本統(tǒng)稱為 AR(Assigned Replicas)。所有與 leader 副本保持一定程度同步的副本(包括 leader 副本在內(nèi))組成 ISR(In-Sync Replicas),ISR 集合是 AR 集合中的一個(gè)子集。消息會(huì)先發(fā)送到 leader 副本,然后 follower 副本才能從 leader 副本中拉取消息進(jìn)行同步,同步期間內(nèi) follower 副本相對(duì)于 leader 副本而言會(huì)有一定程度的滯后。
前面所說的 “一定程度的同步” 是指可忍受的滯后范圍,這個(gè)范圍可以通過參數(shù)進(jìn)行配置。與 leader 副本同步滯后過多的副本(不包括 leader 副本)組成 OSR(Out-of-Sync Replicas),由此可見,AR=ISR+OSR。在正常情況下,所有的 follower 副本都應(yīng)該與 leader 副本保持一定程度的同步,即 AR=ISR,OSR 集合為空。
leader 副本負(fù)責(zé)維護(hù)和跟蹤 ISR 集合中所有 follower 副本的滯后狀態(tài),當(dāng) follower 副本落后太多或失效時(shí),leader 副本會(huì)把它從 ISR 集合中剔除。如果 OSR 集合中有 follower 副本“追上”了 leader 副本,那么 leader 副本會(huì)把它從 OSR 集合轉(zhuǎn)移至 ISR 集合。默認(rèn)情況下,當(dāng) leader 副本發(fā)生故障時(shí),只有在 ISR 集合中的副本才有資格被選舉為新的 leader,而在 OSR 集合中的副本則沒有任何機(jī)會(huì)(不過這個(gè)原則也可以通過修改相應(yīng)的參數(shù)配置來改變)。
HW & LEO
ISR 與 HW 和 LEO 也有緊密的關(guān)系。HW 是 High Watermark 的縮寫,俗稱高水位,它標(biāo)識(shí)了一個(gè)特定的消息偏移量(offset),消費(fèi)者只能拉取到這個(gè) offset 之前的消息。
如上圖所示,它代表一個(gè)日志文件,這個(gè)日志文件中有 9 條消息,第一條消息的 offset(LogStartOffset)為 0,最后一條消息的 offset 為 8,offset 為 9 的消息用虛線框表示,代表下一條待寫入的消息。日志文件的 HW 為 6,表示消費(fèi)者只能拉取到 offset 在 0 至 5 之間的消息,而 offset 為 6 的消息對(duì)消費(fèi)者而言是不可見的。
LEO 是 Log End Offset 的縮寫,它標(biāo)識(shí)當(dāng)前日志文件中下一條待寫入消息的 offset,上圖中 offset 為 9 的位置即為當(dāng)前日志文件的 LEO,LEO 的大小相當(dāng)于當(dāng)前日志分區(qū)中最后一條消息的 offset 值加 1。分區(qū) ISR 集合中的每個(gè)副本都會(huì)維護(hù)自身的 LEO ,而 ISR 集合中最小的 LEO 即為分區(qū)的 HW,對(duì)消費(fèi)者而言只能消費(fèi) HW 之前的消息。
小貼士:很多資料中誤將上圖中的 offset 為 5 的位置看作 HW,而把 offset 為 8 的位置看作 LEO,這顯然是不對(duì)的。
為了更好地理解 ISR 集合,以及 HW 和 LEO 之間的關(guān)系,下面通過一個(gè)簡(jiǎn)單的示例來進(jìn)行相關(guān)的說明。如上圖所示,假設(shè)某個(gè)分區(qū)的 ISR 集合中有 3 個(gè)副本,即 1 個(gè) leader 副本和 2 個(gè) follower 副本,此時(shí)分區(qū)的 LEO 和 HW 都為 3。消息 3 和消息 4 從生產(chǎn)者發(fā)出之后會(huì)被先存入 leader 副本,如下圖所示。
在消息寫入 leader 副本之后,follower 副本會(huì)發(fā)送拉取請(qǐng)求來拉取消息 3 和消息 4 以進(jìn)行消息同步(這里有一個(gè)疑問: follower 副本是定時(shí)去 leader 副本中拉數(shù)據(jù)進(jìn)行同步,還是 leader 副本有新消息進(jìn)入后通知 follower 副本來拉消息)。
在同步過程中,不同的 follower 副本的同步效率也不盡相同。如上圖所示,在某一時(shí)刻 follower1 完全跟上了 leader 副本而 follower 2 只同步了消息 3,如此 leader 副本的 LEO 為 5,follower 1 的 LEO 為 5,follower 2 的 LEO 為 4,那么當(dāng)前分區(qū)的 HW 取最小值 4,此時(shí)消費(fèi)者可以消費(fèi)到 offset 為 0 至 3 之間的消息。
小貼士:消費(fèi)者能夠消費(fèi)到的消息一定是分區(qū)中 ISR 副本已經(jīng)同步完成的消息,這種方式就很好了規(guī)避了有一些同步滯后的副本同步速度慢的問題,從而影響性能。
寫入消息(情形 4)如下圖所示,所有的副本都成功寫入了消息 3 和消息 4,整個(gè)分區(qū)的 HW 和 LEO 都變?yōu)?5,因此消費(fèi)者可以消費(fèi)到 offset 為 4 的消息了。
由此可見,Kafka 的復(fù)制機(jī)制既不是完全的同步復(fù)制,也不是單純的異步復(fù)制。事實(shí)上,同步復(fù)制要求所有能工作的 follower 副本都復(fù)制完,這條消息才會(huì)被確認(rèn)為已成功提交,這種復(fù)制方式極大地影響了性能。而在異步復(fù)制方式下,follower 副本異步地從 leader 副本中復(fù)制數(shù)據(jù),數(shù)據(jù)只要被 leader 副本寫入就被認(rèn)為已經(jīng)成功提交。在這種情況下,如果 follower 副本都還沒有復(fù)制完而落后于 leader 副本,突然 leader 副本宕機(jī),則會(huì)造成數(shù)據(jù)丟失。Kafka 使用的這種 ISR 的 HW 和 LEO 方式 則有效地權(quán)衡了 數(shù)據(jù)可靠性和性能之間的關(guān)系 。
轉(zhuǎn)載于:https://www.cnblogs.com/tkzL/p/11414185.html
總結(jié)
- 上一篇: 程序员版《后浪》
- 下一篇: 系统架构性能优化思路