[TOC]
1 簡介
MQ滿天飛的時代踏幻,kafka也只是其中之一。
Kafka泽论,一個基于分布式
的高吞吐量
的消息發(fā)布-訂閱系統(tǒng)
艾少。
具有快速
、持久
翼悴、可擴展
缚够、處理大量不同消費者
的特性。Kafka 不會關(guān)心消息的處理過程及消費者隊列鹦赎。
- 磁盤線性讀寫谍椅,
O(1)
讀寫性能 - 高吞吐量
- 顯式的
分布式
架構(gòu)
詳細的介紹可以看這里:http://blog.cloudera.com/blog/2014/09/apache-kafka-for-beginners/
2 名詞解釋
- broker
kafka集群中的服務器(一個或多個)被稱為broker
。
- topic
顧名思義,topic就是主題的意思古话。也就是對消息的一個分類雏吭。kafka中的每個消息都有一個分類/類別,這個類別就是topic陪踩。
不同topic的消息在磁盤上是分開存儲的杖们,同時對消費者是透明的。也就是說當你消費消息的時候并不需要知道消息是怎么存儲的肩狂,也不需要知道存儲在哪里摘完。
- partition
可以認為是topic的物理分組,一個topic可以分為一個或多個partition。partition一兩句話說不清傻谁,詳情見后面的小節(jié)孝治。
- producer
這個好理解,就是消息的生產(chǎn)者审磁。
- consumer
和producer相對應荆秦,consumer就是消息的消費者。通常是各種高級語言寫的客戶端API力图,比如Java步绸、Python甚至是JavaScript所寫的客戶端API。
- consumer group
每個consumer都屬于一個消費者組
吃媒。不顯示地指定消費者組的時候?qū)儆谀J的消費者組瓤介。
- message
消息是通信的基本單位,producer
可以向topic
發(fā)布message
赘那。新發(fā)布的消息就會廣播給訂閱了這個主題de consumer刑桑。message只能傳輸給某個group中的某一個consumer。
3 partition
kafka作為一個MQ或者日志系統(tǒng)募舟,他的最終數(shù)據(jù)存儲還是離不開磁盤的祠斧。kafka對每個消息做了分類,即有了topic拱礁,每個topic當然也是持久化在磁盤上的琢锋。當消費完之后太過于陳舊的消息(message/topic)將被刪除辕漂。
鑒于此,將所有topic都存儲在同一個目錄里將導致磁盤文件太過于龐大吴超,這樣一來钉嘹,管理不便,如果一個磁盤掛了鲸阻,將導致所有數(shù)據(jù)丟失跋涣;而且磁盤的空間總是有限的。也就是說一個磁盤持久化所有數(shù)據(jù)在生成環(huán)境是不靠譜的鸟悴。
所以陈辱,kafka可以將不同的topic分布式地存儲于不同的磁盤上,這就有了kafka所謂的partition的概念细诸。
partition是一個有序的沛贪、不可變的消息隊列。每個消息都有一個連續(xù)的序列號即offset
揍堰。每個partition又分為若干個segment
鹏浅。
最簡單的也就是kafka默認的partition分布存儲策略就是hash了。簡單理解就是所有可用的broker一次輪流一個一個地存儲partition屏歹。
這么一搞隐砸,最終結(jié)果就是:
- 每臺可用的broker上的數(shù)據(jù)逗比總數(shù)據(jù)要少
- 但是每個消息數(shù)據(jù)都有冗余
- 一般情況下,一臺broker宕機并不影響整個系統(tǒng)(當然如果你只有一臺broker那就另說了……)
日志文件的存儲位置(partition就在這里了)在server.properties中指定: log.dirs=/Users/hylexus/data/kafka/kafka-logs
蝙眶。
3.1 單機版partition的磁盤存儲
此處先從單機版kafka中partition存儲方式說起季希。
單機版并沒有partition帶來的好處。
本人此處的設(shè)置是kafka數(shù)據(jù)存儲在log.dirs=/Users/hylexus/data/kafka/kafka-logs
幽纷。
創(chuàng)建一個測試用的topic名為topic01
$ bin/kafka-topics.sh --create \
--zookeeper localhost:2181 \
--replication-factor 1 \
--partitions 4 \ # 分區(qū)數(shù)為4
--topic topic01
查看磁盤上partition的存儲
hylexus@hylexusPC kafka-logs $ pwd
/Users/hylexus/data/kafka/kafka-logs
hylexus@hylexusPC kafka-logs $ ll
drwxr-xr-x 5 hylexus staff 170 5 1 15:46 topic01-0
drwxr-xr-x 5 hylexus staff 170 5 1 15:46 topic01-1
drwxr-xr-x 5 hylexus staff 170 5 1 15:46 topic01-2
drwxr-xr-x 5 hylexus staff 170 5 1 15:46 topic01-3
hylexus@hylexusPC kafka-logs $
單機版由于只有一個目錄,partition分布較為簡單式塌。
3.2 多broker下partition的磁盤存儲
此處的多broker是如下形式:
單機上啟動三個broker,注冊到同一個zookeeper。
創(chuàng)建一個topic名為topic02,用以測試
bin/kafka-topics.sh --create \
--zookeeper localhost:2181 \
--replication-factor 2 \ # 2份拷貝
--partitions 4 \ # 4個partition
--topic topic02
查看磁盤磁盤上partition存儲
hylexus@hylexusPC kafka-logs $ pwd
/Users/hylexus/data/kafka/kafka-logs
hylexus@hylexusPC kafka-logs $ ll
drwxr-xr-x 5 hylexus staff 170 5 1 16:29 topic02-0
drwxr-xr-x 5 hylexus staff 170 5 1 16:29 topic02-2
drwxr-xr-x 5 hylexus staff 170 5 1 16:29 topic02-3
hylexus@hylexusPC kafka-logs-02 $ pwd
/Users/hylexus/data/kafka/kafka-logs-02
hylexus@hylexusPC kafka-logs-02 $ ll
drwxr-xr-x 5 hylexus staff 170 5 1 16:29 topic02-0
drwxr-xr-x 5 hylexus staff 170 5 1 16:29 topic02-1
drwxr-xr-x 5 hylexus staff 170 5 1 16:29 topic02-3
hylexus@hylexusPC kafka-logs-03 $ pwd
/Users/hylexus/data/kafka/kafka-logs-03
hylexus@hylexusPC kafka-logs-03 $ ll
drwxr-xr-x 5 hylexus staff 170 5 1 16:29 topic02-1
drwxr-xr-x 5 hylexus staff 170 5 1 16:29 topic02-2
此時的partition磁盤分布如下:
記broker個數(shù)為n,則有:
- 第i個partition分配到第
(i % n)
個broker - 第i個Partition的第j個拷貝分配到第
((i + j) % n)
個broker
3.3 partition磁盤存儲總結(jié)
- 每個partition為一個目錄
- partiton命名規(guī)則為
topic名稱
-有序序號
- 第一個partiton有序序號從0開始
- 序號最大值為partitions數(shù)量減1
- 如果你只是調(diào)用kafka提供的客戶端程序的話友浸,你沒有必要清楚每個partition是怎么分布的峰尝,因為你只是調(diào)用客戶端消費數(shù)據(jù)而已
3.4 partition中segment磁盤存儲
接著上面說的,其實每個partition就相當于一個大型文件(整個消息記錄)被分配到多個大小相等的文件中存儲收恢。大小相等但是消息個數(shù)不一定相等了武学,這樣利于管理,可以快速的刪除陳舊的文件伦意,有效地提高了磁盤的利用率火窒。
此處所說的每個大小相等的文件就是segment(partition的再次細分)了。
既然數(shù)據(jù)是存儲在磁盤上的驮肉,即便比不上磁盤高效熏矿,但也要在一個MQ系統(tǒng)能接受的范圍內(nèi)。
所以,索引就必不可少了票编,kafka的segment文件分為兩個主要部分:index+log
- index主要是索引文件褪储,log才是真正的消息數(shù)據(jù)。
- segment文件命名時:
- 第一個segment文件名稱從零開始,前導零填充至19位
- 其他每個segment文件名為上一個segment文件最后一個message的offset
此處就以單機版的kafka為例:
為測試方便,此處我將log.segment.bytes=1024
調(diào)整為1024,以便快速看到效果,生成一些message之后栏妖,topic01-0磁盤存儲如下:
hylexus@hylexusPC topic01-0 $ pwd
/Users/hylexus/data/kafka/kafka-logs/topic01-0
hylexus@hylexusPC kafka-logs $ ll topic01-0
-rw-r--r-- 1 hylexus staff 0 5 1 19:43 00000000000000000000.index
-rw-r--r-- 1 hylexus staff 990 5 1 19:43 00000000000000000000.log
-rw-r--r-- 1 hylexus staff 0 5 1 19:43 00000000000000000012.index
-rw-r--r-- 1 hylexus staff 990 5 1 19:43 00000000000000000012.log
-rw-r--r-- 1 hylexus staff 0 5 1 19:43 00000000000000000024.index
-rw-r--r-- 1 hylexus staff 998 5 1 19:43 00000000000000000024.log
-rw-r--r-- 1 hylexus staff 0 5 1 19:43 00000000000000000036.index
-rw-r--r-- 1 hylexus staff 994 5 1 19:43 00000000000000000036.log
-rw-r--r-- 1 hylexus staff 0 5 1 19:43 00000000000000000048.index
-rw-r--r-- 1 hylexus staff 1004 5 1 19:43 00000000000000000048.log
3.5 通過offset查找message
就拿上面的segment來說乱豆,第一個segment的命名為零(前導零).{index,log}奖恰。
另外吊趾,上面我將每個segment的大小設(shè)置為1024即log.segment.bytes=1024
。
00000000000000000000 offset=0
00000000000000000012 offset=12+1==13
00000000000000000024 offset=24+1==25
……
因此瑟啃,通過offset查找具體消息步驟如下:
- 二分查找定位到segment
- 在某個具體的segment文件中順序查找到具體message
- 另外论泛,為效率考慮,index所以文件是直接映射到內(nèi)存的
例如:查找offset==23的message
- 二分查找到具體segment為00000000000000000012
- 在00000000000000000012內(nèi)部順序找到offset=23的message