為獲得更好的閱讀體驗,建議您訪問原文地址:傳送門
前言:在之前的文章里面已經(jīng)了解到了「消息隊列」是怎么樣的一種存在(傳送門)祈坠,Kafka 作為當下流行的一種中間件害碾,我們現(xiàn)在開始學習它!
一赦拘、Kafka 簡介
Kafka 創(chuàng)建背景
Kafka 是一個消息系統(tǒng)慌随,原本開發(fā)自 LinkedIn,用作 LinkedIn 的活動流(Activity Stream)和運營數(shù)據(jù)處理管道(Pipeline)的基礎(chǔ)×砑ǎ現(xiàn)在它已被多家不同類型的公司 作為多種類型的數(shù)據(jù)管道和消息系統(tǒng)使用儒陨。
活動流數(shù)據(jù)是幾乎所有站點在對其網(wǎng)站使用情況做報表時都要用到的數(shù)據(jù)中最常規(guī)的部分∷褡眩活動數(shù)據(jù)包括頁面訪問量(Page View)蹦漠、被查看內(nèi)容方面的信息以及搜索情況等內(nèi)容。這種數(shù)據(jù)通常的處理方式是先把各種活動以日志的形式寫入某種文件车海,然后周期性地對這些文件進行統(tǒng)計分析笛园。運營數(shù)據(jù)指的是服務(wù)器的性能數(shù)據(jù)(CPU、IO 使用率侍芝、請求時間研铆、服務(wù)日志等等數(shù)據(jù))。運營數(shù)據(jù)的統(tǒng)計方法種類繁多州叠。
近年來棵红,活動和運營數(shù)據(jù)處理已經(jīng)成為了網(wǎng)站軟件產(chǎn)品特性中一個至關(guān)重要的組成部分,這就需要一套稍微更加復(fù)雜的基礎(chǔ)設(shè)施對其提供支持咧栗。
Kafka 簡介
Kafka 是一種分布式的逆甜,基于發(fā)布 / 訂閱的消息系統(tǒng)。主要設(shè)計目標如下:
- 以時間復(fù)雜度為 O(1) 的方式提供消息持久化能力,即使對 TB 級以上數(shù)據(jù)也能保證常數(shù)時間復(fù)雜度的訪問性能。
- 高吞吐率忌锯。即使在非常廉價的商用機器上也能做到單機支持每秒 100K 條以上消息的傳輸箍鼓。
- 支持 Kafka Server 間的消息分區(qū),及分布式消費,同時保證每個 Partition 內(nèi)的消息順序傳輸。
- 同時支持離線數(shù)據(jù)處理和實時數(shù)據(jù)處理。
- Scale out:支持在線水平擴展御毅。
Kafka 基礎(chǔ)概念
概念一:生產(chǎn)者與消費者
對于 Kafka 來說客戶端有兩種基本類型:生產(chǎn)者(Producer)和消費者(Consumer)。除此之外怜珍,還有用來做數(shù)據(jù)集成的 Kafka Connect API 和流式處理的 Kafka Streams 等高階客戶端亚享,但這些高階客戶端底層仍然是生產(chǎn)者和消費者API,它們只不過是在上層做了封裝绘面。
這很容易理解欺税,生產(chǎn)者(也稱為發(fā)布者)創(chuàng)建消息侈沪,而消費者(也稱為訂閱者)負責消費or讀取消息。
概念二:主題(Topic)與分區(qū)(Partition)
在 Kafka 中晚凿,消息以主題(Topic)來分類亭罪,每一個主題都對應(yīng)一個「消息隊列」,這有點兒類似于數(shù)據(jù)庫中的表歼秽。但是如果我們把所有同類的消息都塞入到一個“中心”隊列中应役,勢必缺少可伸縮性,無論是生產(chǎn)者/消費者數(shù)目的增加燥筷,還是消息數(shù)量的增加箩祥,都可能耗盡系統(tǒng)的性能或存儲。
我們使用一個生活中的例子來說明:現(xiàn)在 A 城市生產(chǎn)的某商品需要運輸?shù)?B 城市肆氓,走的是公路袍祖,那么單通道的高速公路不論是在「A 城市商品增多」還是「現(xiàn)在 C 城市也要往 B 城市運輸東西」這樣的情況下都會出現(xiàn)「吞吐量不足」的問題。所以我們現(xiàn)在引入分區(qū)(Partition)的概念谢揪,類似“允許多修幾條道”的方式對我們的主題完成了水平擴展蕉陋。
概念三:Broker 和集群(Cluster)
一個 Kafka 服務(wù)器也稱為 Broker,它接受生產(chǎn)者發(fā)送的消息并存入磁盤拨扶;Broker 同時服務(wù)消費者拉取分區(qū)消息的請求凳鬓,返回目前已經(jīng)提交的消息。使用特定的機器硬件患民,一個 Broker 每秒可以處理成千上萬的分區(qū)和百萬量級的消息缩举。(現(xiàn)在動不動就百萬量級..我特地去查了一把,好像確實集群的情況下吞吐量挺高的..摁..)
若干個 Broker 組成一個集群(Cluster)匹颤,其中集群內(nèi)某個 Broker 會成為集群控制器(Cluster Controller)蚁孔,它負責管理集群,包括分配分區(qū)到 Broker惋嚎、監(jiān)控 Broker 故障等。在集群內(nèi)站刑,一個分區(qū)由一個 Broker 負責另伍,這個 Broker 也稱為這個分區(qū)的 Leader;當然一個分區(qū)可以被復(fù)制到多個 Broker 上來實現(xiàn)冗余绞旅,這樣當存在 Broker 故障時可以將其分區(qū)重新分配到其他 Broker 來負責摆尝。下圖是一個樣例:
Kafka 的一個關(guān)鍵性質(zhì)是日志保留(retention),我們可以配置主題的消息保留策略因悲,譬如只保留一段時間的日志或者只保留特定大小的日志堕汞。當超過這些限制時,老的消息會被刪除晃琳。我們也可以針對某個主題單獨設(shè)置消息過期策略讯检,這樣對于不同應(yīng)用可以實現(xiàn)個性化琐鲁。
概念四:多集群
隨著業(yè)務(wù)發(fā)展,我們往往需要多集群人灼,通常處于下面幾個原因:
- 基于數(shù)據(jù)的隔離围段;
- 基于安全的隔離;
- 多數(shù)據(jù)中心(容災(zāi))
當構(gòu)建多個數(shù)據(jù)中心時投放,往往需要實現(xiàn)消息互通奈泪。舉個例子,假如用戶修改了個人資料灸芳,那么后續(xù)的請求無論被哪個數(shù)據(jù)中心處理涝桅,這個更新需要反映出來。又或者烙样,多個數(shù)據(jù)中心的數(shù)據(jù)需要匯總到一個總控中心來做數(shù)據(jù)分析冯遂。
上面說的分區(qū)復(fù)制冗余機制只適用于同一個 Kafka 集群內(nèi)部,對于多個 Kafka 集群消息同步可以使用 Kafka 提供的 MirrorMaker 工具误阻。本質(zhì)上來說债蜜,MirrorMaker 只是一個 Kafka 消費者和生產(chǎn)者,并使用一個隊列連接起來而已究反。它從一個集群中消費消息寻定,然后往另一個集群生產(chǎn)消息。
二精耐、Kafka 的設(shè)計與實現(xiàn)
上面我們知道了 Kafka 中的一些基本概念狼速,但作為一個成熟的「消息隊列」中間件,其中有許多有意思的設(shè)計值得我們思考卦停,下面我們簡單列舉一些向胡。
討論一:Kafka 存儲在文件系統(tǒng)上
是的,您首先應(yīng)該知道 Kafka 的消息是存在于文件系統(tǒng)之上的惊完。Kafka 高度依賴文件系統(tǒng)來存儲和緩存消息僵芹,一般的人認為 “磁盤是緩慢的”,所以對這樣的設(shè)計持有懷疑態(tài)度小槐。實際上拇派,磁盤比人們預(yù)想的快很多也慢很多,這取決于它們?nèi)绾伪皇褂迷涮灰粋€好的磁盤結(jié)構(gòu)設(shè)計可以使之跟網(wǎng)絡(luò)速度一樣快件豌。
現(xiàn)代的操作系統(tǒng)針對磁盤的讀寫已經(jīng)做了一些優(yōu)化方案來加快磁盤的訪問速度。比如控嗜,預(yù)讀會提前將一個比較大的磁盤快讀入內(nèi)存茧彤。后寫會將很多小的邏輯寫操作合并起來組合成一個大的物理寫操作。并且疆栏,操作系統(tǒng)還會將主內(nèi)存剩余的所有空閑內(nèi)存空間都用作磁盤緩存曾掂,所有的磁盤讀寫操作都會經(jīng)過統(tǒng)一的磁盤緩存(除了直接 I/O 會繞過磁盤緩存)惫谤。綜合這幾點優(yōu)化特點,如果是針對磁盤的順序訪問遭殉,某些情況下它可能比隨機的內(nèi)存訪問都要快石挂,甚至可以和網(wǎng)絡(luò)的速度相差無幾。
上述的 Topic 其實是邏輯上的概念险污,面相消費者和生產(chǎn)者痹愚,物理上存儲的其實是 Partition,每一個 Partition 最終對應(yīng)一個目錄蛔糯,里面存儲所有的消息和索引文件拯腮。默認情況下,每一個 Topic 在創(chuàng)建時如果不指定 Partition 數(shù)量時只會創(chuàng)建 1 個 Partition蚁飒。比如动壤,我創(chuàng)建了一個 Topic 名字為 test ,沒有指定 Partition 的數(shù)量淮逻,那么會默認創(chuàng)建一個 test-0 的文件夾琼懊,這里的命名規(guī)則是:<topic_name>-<partition_id>
。
任何發(fā)布到 Partition 的消息都會被追加到 Partition 數(shù)據(jù)文件的尾部爬早,這樣的順序?qū)懘疟P操作讓 Kafka 的效率非常高(經(jīng)驗證哼丈,順序?qū)懘疟P效率比隨機寫內(nèi)存還要高,這是 Kafka 高吞吐率的一個很重要的保證)筛严。
每一條消息被發(fā)送到 Broker 中醉旦,會根據(jù) Partition 規(guī)則選擇被存儲到哪一個 Partition。如果 Partition 規(guī)則設(shè)置的合理桨啃,所有消息可以均勻分布到不同的 Partition中车胡。
討論二:Kafka 中的底層存儲設(shè)計
假設(shè)我們現(xiàn)在 Kafka 集群只有一個 Broker,我們創(chuàng)建 2 個 Topic 名稱分別為:「topic1」和「topic2」照瘾,Partition 數(shù)量分別為 1匈棘、2,那么我們的根目錄下就會創(chuàng)建如下三個文件夾:
| --topic1-0
| --topic2-0
| --topic2-1
在 Kafka 的文件存儲中析命,同一個 Topic 下有多個不同的 Partition主卫,每個 Partition 都為一個目錄,而每一個目錄又被平均分配成多個大小相等的 Segment File 中碳却,Segment File 又由 index file 和 data file 組成,他們總是成對出現(xiàn)笑旺,后綴 ".index" 和 ".log" 分表表示 Segment 索引文件和數(shù)據(jù)文件昼浦。
現(xiàn)在假設(shè)我們設(shè)置每個 Segment 大小為 500 MB,并啟動生產(chǎn)者向 topic1 中寫入大量數(shù)據(jù)筒主,topic1-0 文件夾中就會產(chǎn)生類似如下的一些文件:
| --topic1-0
| --00000000000000000000.index
| --00000000000000000000.log
| --00000000000000368769.index
| --00000000000000368769.log
| --00000000000000737337.index
| --00000000000000737337.log
| --00000000000001105814.index
| --00000000000001105814.log
| --topic2-0
| --topic2-1
Segment 是 Kafka 文件存儲的最小單位关噪。Segment 文件命名規(guī)則:Partition 全局的第一個 Segment 從 0 開始鸟蟹,后續(xù)每個 Segment 文件名為上一個 Segment 文件最后一條消息的 offset 值。數(shù)值最大為 64 位 long 大小使兔,19 位數(shù)字字符長度建钥,沒有數(shù)字用0填充。如 00000000000000368769.index 和 00000000000000368769.log虐沥。
以上面的一對 Segment File 為例熊经,說明一下索引文件和數(shù)據(jù)文件對應(yīng)關(guān)系:
其中以索引文件中元數(shù)據(jù) <3, 497>
為例,依次在數(shù)據(jù)文件中表示第 3 個 message(在全局 Partition 表示第 368769 + 3 = 368772 個 message)以及該消息的物理偏移地址為 497欲险。
注意該 index 文件并不是從0開始镐依,也不是每次遞增1的,這是因為 Kafka 采取稀疏索引存儲的方式天试,每隔一定字節(jié)的數(shù)據(jù)建立一條索引槐壳,它減少了索引文件大小,使得能夠把 index 映射到內(nèi)存喜每,降低了查詢時的磁盤 IO 開銷务唐,同時也并沒有給查詢帶來太多的時間消耗。
因為其文件名為上一個 Segment 最后一條消息的 offset 带兜,所以當需要查找一個指定 offset 的 message 時枫笛,通過在所有 segment 的文件名中進行二分查找就能找到它歸屬的 segment ,再在其 index 文件中找到其對應(yīng)到文件上的物理位置鞋真,就能拿出該 message 崇堰。
由于消息在 Partition 的 Segment 數(shù)據(jù)文件中是順序讀寫的,且消息消費后不會刪除(刪除策略是針對過期的 Segment 文件)涩咖,這種順序磁盤 IO 存儲設(shè)計師 Kafka 高性能很重要的原因海诲。
Kafka 是如何準確的知道 message 的偏移的呢?這是因為在 Kafka 定義了標準的數(shù)據(jù)存儲結(jié)構(gòu)檩互,在 Partition 中的每一條 message 都包含了以下三個屬性:
- offset:表示 message 在當前 Partition 中的偏移量特幔,是一個邏輯上的值,唯一確定了 Partition 中的一條 message闸昨,可以簡單的認為是一個 id蚯斯;
- MessageSize:表示 message 內(nèi)容 data 的大小饵较;
- data:message 的具體內(nèi)容
討論三:生產(chǎn)者設(shè)計概要
當我們發(fā)送消息之前拍嵌,先問幾個問題:每條消息都是很關(guān)鍵且不能容忍丟失么?偶爾重復(fù)消息可以么循诉?我們關(guān)注的是消息延遲還是寫入消息的吞吐量横辆?
舉個例子,有一個信用卡交易處理系統(tǒng)茄猫,當交易發(fā)生時會發(fā)送一條消息到 Kafka狈蚤,另一個服務(wù)來讀取消息并根據(jù)規(guī)則引擎來檢查交易是否通過困肩,將結(jié)果通過 Kafka 返回。對于這樣的業(yè)務(wù)脆侮,消息既不能丟失也不能重復(fù)锌畸,由于交易量大因此吞吐量需要盡可能大,延遲可以稍微高一點靖避。
再舉個例子潭枣,假如我們需要收集用戶在網(wǎng)頁上的點擊數(shù)據(jù),對于這樣的場景筋蓖,少量消息丟失或者重復(fù)是可以容忍的卸耘,延遲多大都不重要只要不影響用戶體驗,吞吐則根據(jù)實時用戶數(shù)來決定粘咖。
不同的業(yè)務(wù)需要使用不同的寫入方式和配置蚣抗。具體的方式我們在這里不做討論,現(xiàn)在先看下生產(chǎn)者寫消息的基本流程:
流程如下:
- 首先瓮下,我們需要創(chuàng)建一個ProducerRecord翰铡,這個對象需要包含消息的主題(topic)和值(value),可以選擇性指定一個鍵值(key)或者分區(qū)(partition)讽坏。
- 發(fā)送消息時锭魔,生產(chǎn)者會對鍵值和值序列化成字節(jié)數(shù)組,然后發(fā)送到分配器(partitioner)路呜。
- 如果我們指定了分區(qū)迷捧,那么分配器返回該分區(qū)即可;否則胀葱,分配器將會基于鍵值來選擇一個分區(qū)并返回漠秋。
- 選擇完分區(qū)后,生產(chǎn)者知道了消息所屬的主題和分區(qū)抵屿,它將這條記錄添加到相同主題和分區(qū)的批量消息中庆锦,另一個線程負責發(fā)送這些批量消息到對應(yīng)的Kafka broker。
- 當broker接收到消息后轧葛,如果成功寫入則返回一個包含消息的主題搂抒、分區(qū)及位移的RecordMetadata對象,否則返回異常尿扯。
- 生產(chǎn)者接收到結(jié)果后求晶,對于異常可能會進行重試衷笋。
討論四:消費者設(shè)計概要
消費者與消費組
假設(shè)這么個場景:我們從Kafka中讀取消息芳杏,并且進行檢查,最后產(chǎn)生結(jié)果數(shù)據(jù)。我們可以創(chuàng)建一個消費者實例去做這件事情蚜锨,但如果生產(chǎn)者寫入消息的速度比消費者讀取的速度快怎么辦呢?這樣隨著時間增長慢蜓,消息堆積越來越嚴重亚再。對于這種場景,我們需要增加多個消費者來進行水平擴展晨抡。
Kafka消費者是消費組的一部分氛悬,當多個消費者形成一個消費組來消費主題時,每個消費者會收到不同分區(qū)的消息耘柱。假設(shè)有一個T1主題如捅,該主題有4個分區(qū);同時我們有一個消費組G1调煎,這個消費組只有一個消費者C1镜遣。那么消費者C1將會收到這4個分區(qū)的消息,如下所示:
如果我們增加新的消費者C2到消費組G1士袄,那么每個消費者將會分別收到兩個分區(qū)的消息悲关,如下所示:
如果增加到4個消費者,那么每個消費者將會分別收到一個分區(qū)的消息娄柳,如下所示:
但如果我們繼續(xù)增加消費者到這個消費組寓辱,剩余的消費者將會空閑,不會收到任何消息:
總而言之赤拒,我們可以通過增加消費組的消費者來進行水平擴展提升消費能力秫筏。這也是為什么建議創(chuàng)建主題時使用比較多的分區(qū)數(shù),這樣可以在消費負載高的情況下增加消費者來提升性能挎挖。另外这敬,消費者的數(shù)量不應(yīng)該比分區(qū)數(shù)多,因為多出來的消費者是空閑的肋乍,沒有任何幫助鹅颊。
Kafka一個很重要的特性就是,只需寫入一次消息墓造,可以支持任意多的應(yīng)用讀取這個消息堪伍。換句話說,每個應(yīng)用都可以讀到全量的消息觅闽。為了使得每個應(yīng)用都能讀到全量消息帝雇,應(yīng)用需要有不同的消費組。對于上面的例子蛉拙,假如我們新增了一個新的消費組G2尸闸,而這個消費組有兩個消費者,那么會是這樣的:
在這個場景中,消費組G1和消費組G2都能收到T1主題的全量消息吮廉,在邏輯意義上來說它們屬于不同的應(yīng)用苞尝。
最后,總結(jié)起來就是:如果應(yīng)用需要讀取全量消息宦芦,那么請為該應(yīng)用設(shè)置一個消費組宙址;如果該應(yīng)用消費能力不足,那么可以考慮在這個消費組里增加消費者调卑。
消費組與分區(qū)重平衡
可以看到抡砂,當新的消費者加入消費組,它會消費一個或多個分區(qū)恬涧,而這些分區(qū)之前是由其他消費者負責的注益;另外,當消費者離開消費組(比如重啟溯捆、宕機等)時丑搔,它所消費的分區(qū)會分配給其他分區(qū)。這種現(xiàn)象稱為重平衡(rebalance)提揍。重平衡是 Kafka 一個很重要的性質(zhì)低匙,這個性質(zhì)保證了高可用和水平擴展。不過也需要注意到碳锈,在重平衡期間顽冶,所有消費者都不能消費消息,因此會造成整個消費組短暫的不可用售碳。而且强重,將分區(qū)進行重平衡也會導(dǎo)致原來的消費者狀態(tài)過期,從而導(dǎo)致消費者需要重新更新狀態(tài)贸人,這段期間也會降低消費性能间景。后面我們會討論如何安全的進行重平衡以及如何盡可能避免。
消費者通過定期發(fā)送心跳(hearbeat)到一個作為組協(xié)調(diào)者(group coordinator)的 broker 來保持在消費組內(nèi)存活艺智。這個 broker 不是固定的倘要,每個消費組都可能不同。當消費者拉取消息或者提交時十拣,便會發(fā)送心跳封拧。
如果消費者超過一定時間沒有發(fā)送心跳,那么它的會話(session)就會過期夭问,組協(xié)調(diào)者會認為該消費者已經(jīng)宕機泽西,然后觸發(fā)重平衡$智鳎可以看到捧杉,從消費者宕機到會話過期是有一定時間的陕见,這段時間內(nèi)該消費者的分區(qū)都不能進行消息消費;通常情況下味抖,我們可以進行優(yōu)雅關(guān)閉评甜,這樣消費者會發(fā)送離開的消息到組協(xié)調(diào)者,這樣組協(xié)調(diào)者可以立即進行重平衡而不需要等待會話過期仔涩。
在 0.10.1 版本蜕着,Kafka 對心跳機制進行了修改,將發(fā)送心跳與拉取消息進行分離红柱,這樣使得發(fā)送心跳的頻率不受拉取的頻率影響。另外更高版本的 Kafka 支持配置一個消費者多長時間不拉取消息但仍然保持存活蓖乘,這個配置可以避免活鎖(livelock)锤悄。活鎖嘉抒,是指應(yīng)用沒有故障但是由于某些原因不能進一步消費零聚。
Partition 與消費模型
上面提到,Kafka 中一個 topic 中的消息是被打散分配在多個 Partition(分區(qū)) 中存儲的些侍, Consumer Group 在消費時需要從不同的 Partition 獲取消息隶症,那最終如何重建出 Topic 中消息的順序呢?
答案是:沒有辦法岗宣。Kafka 只會保證在 Partition 內(nèi)消息是有序的蚂会,而不管全局的情況。
下一個問題是:Partition 中的消息可以被(不同的 Consumer Group)多次消費耗式,那 Partition中被消費的消息是何時刪除的胁住? Partition 又是如何知道一個 Consumer Group 當前消費的位置呢?
無論消息是否被消費刊咳,除非消息到期 Partition 從不刪除消息彪见。例如設(shè)置保留時間為 2 天,則消息發(fā)布 2 天內(nèi)任何 Group 都可以消費娱挨,2 天后余指,消息自動被刪除。
Partition 會為每個 Consumer Group 保存一個偏移量跷坝,記錄 Group 消費到的位置酵镜。 如下圖:
為什么 Kafka 是 pull 模型
消費者應(yīng)該向 Broker 要數(shù)據(jù)(pull)還是 Broker 向消費者推送數(shù)據(jù)(push)?作為一個消息系統(tǒng)柴钻,Kafka 遵循了傳統(tǒng)的方式笋婿,選擇由 Producer 向 broker push 消息并由 Consumer 從 broker pull 消息。一些 logging-centric system顿颅,比如 Facebook 的Scribe和 Cloudera 的Flume缸濒,采用 push 模式足丢。事實上,push 模式和 pull 模式各有優(yōu)劣庇配。
push 模式很難適應(yīng)消費速率不同的消費者斩跌,因為消息發(fā)送速率是由 broker 決定的。push 模式的目標是盡可能以最快速度傳遞消息捞慌,但是這樣很容易造成 Consumer 來不及處理消息耀鸦,典型的表現(xiàn)就是拒絕服務(wù)以及網(wǎng)絡(luò)擁塞。而 pull 模式則可以根據(jù) Consumer 的消費能力以適當?shù)乃俾氏M消息啸澡。
對于 Kafka 而言袖订,pull 模式更合適。pull 模式可簡化 broker 的設(shè)計嗅虏,Consumer 可自主控制消費消息的速率洛姑,同時 Consumer 可以自己控制消費方式——即可批量消費也可逐條消費,同時還能選擇不同的提交方式從而實現(xiàn)不同的傳輸語義皮服。
討論五:Kafka 如何保證可靠性
當我們討論可靠性的時候楞艾,我們總會提到保證*這個詞語×涔悖可靠性保證是基礎(chǔ)硫眯,我們基于這些基礎(chǔ)之上構(gòu)建我們的應(yīng)用。比如關(guān)系型數(shù)據(jù)庫的可靠性保證是ACID择同,也就是原子性(Atomicity)两入、一致性(Consistency)、隔離性(Isolation)和持久性(Durability)敲才。
Kafka 中的可靠性保證有如下四點:
- 對于一個分區(qū)來說谆刨,它的消息是有序的。如果一個生產(chǎn)者向一個分區(qū)先寫入消息A归斤,然后寫入消息B痊夭,那么消費者會先讀取消息A再讀取消息B。
- 當消息寫入所有in-sync狀態(tài)的副本后脏里,消息才會認為已提交(committed)她我。這里的寫入有可能只是寫入到文件系統(tǒng)的緩存,不一定刷新到磁盤迫横。生產(chǎn)者可以等待不同時機的確認番舆,比如等待分區(qū)主副本寫入即返回,后者等待所有in-sync狀態(tài)副本寫入才返回矾踱。
- 一旦消息已提交恨狈,那么只要有一個副本存活,數(shù)據(jù)不會丟失呛讲。
- 消費者只能讀取到已提交的消息禾怠。
使用這些基礎(chǔ)保證返奉,我們構(gòu)建一個可靠的系統(tǒng),這時候需要考慮一個問題:究竟我們的應(yīng)用需要多大程度的可靠性吗氏?可靠性不是無償?shù)难科c系統(tǒng)可用性、吞吐量弦讽、延遲和硬件價格息息相關(guān)污尉,得此失彼。因此往产,我們往往需要做權(quán)衡被碗,一味的追求可靠性并不實際。
三仿村、動手搭一個 Kafka
通過上面的描述锐朴,我們已經(jīng)大致了解到了「Kafka」是何方神圣了,現(xiàn)在我們開始嘗試自己動手本地搭一個來實際體驗一把奠宜。
第一步:下載 Kafka
這里以 Mac OS 為例,在安裝了 Homebrew 的情況下執(zhí)行下列代碼:
brew install kafka
由于 Kafka 依賴了 Zookeeper瞻想,所以在下載的時候會自動下載压真。
第二步:啟動服務(wù)
我們在啟動之前首先需要修改 Kafka 的監(jiān)聽地址和端口為 localhost:9092
:
vi /usr/local/etc/kafka/server.properties
然后修改成下圖的樣子:
依次啟動 Zookeeper 和 Kafka:
brew services start zookeeper
brew services start kafka
然后執(zhí)行下列語句來創(chuàng)建一個名字為 "test" 的 Topic:
kafka-topics --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test
我們可以通過下列的命令查看我們的 Topic 列表:
kafka-topics --list --zookeeper localhost:2181
第三步:發(fā)送消息
然后我們新建一個控制臺,運行下列命令創(chuàng)建一個消費者關(guān)注剛才創(chuàng)建的 Topic:
kafka-console-consumer --bootstrap-server localhost:9092 --topic test --from-beginning
用控制臺往剛才創(chuàng)建的 Topic 中添加消息蘑险,并觀察剛才創(chuàng)建的消費者窗口:
kafka-console-producer --broker-list localhost:9092 --topic test
能通過消費者窗口觀察到正確的消息:
參考資料
- https://www.infoq.cn/article/kafka-analysis-part-1 - Kafka 設(shè)計解析(一):Kafka 背景及架構(gòu)介紹
- http://www.dengshenyu.com/%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F/2017/11/06/kafka-Meet-Kafka.html - Kafka系列(一)初識Kafka
- https://lotabout.me/2018/kafka-introduction/ - Kafka 入門介紹
- https://www.zhihu.com/question/28925721 - Kafka 中的 Topic 為什么要進行分區(qū)? - 知乎
- https://blog.joway.io/posts/kafka-design-practice/ - Kafka 的設(shè)計與實踐思考
- http://www.dengshenyu.com/%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F/2017/11/21/kafka-data-delivery.html - Kafka系列(六)可靠的數(shù)據(jù)傳輸
按照慣例黏一個尾巴:
歡迎轉(zhuǎn)載滴肿,轉(zhuǎn)載請注明出處!
獨立域名博客:wmyskxz.com
簡書ID:@我沒有三顆心臟
github:wmyskxz
歡迎關(guān)注公眾微信號:wmyskxz
分享自己的學習 & 學習資料 & 生活
想要交流的朋友也可以加qq群:3382693