Kafka-之資料日誌儲存(格式變化與壓縮)
Kafka-之資料日誌儲存
1 kafka的日誌佈局
kafka的資料儲存是基於檔案系統的,kafka的資料以日誌的形式儲存在磁碟上,具體的日誌佈局可以看下圖。
很明顯,kafka以topic來進行資料劃分,我們可以通過在server.properties
檔案指定log.dirs
來指定資料日誌儲存
#指定日誌儲存路徑
log.dirs=/tmp/kafka-logs1,tmp/kafka-logs2,....
雖說kafka按照topic進行資料劃分,但是在物理儲存上還是按照topic-partition進行目錄劃分,假如這裡有個topicA有2個partition,那麼它的儲存結構如下:
cd /tmp/kafka-logs1/
topicA-0/
#在每個分割槽下的資料又是按日誌分段進行儲存的,每個日誌分段LogSegment都有自己的索引檔案和輔助檔案
00000000000000000000.index # offset索引檔案
00000000000000000000.log # 實際資料日誌
00000000000000000000.timeindex # 時間戳索引檔案
00000000000000000000.txnindex # unknown
00000000000000000000.snapshot # 快照記錄檔案
topicA-1/
.............
kafka的訊息都是順序寫入磁碟的logSegment檔案的,只有最後一個logSegment檔案才能執行寫入操作,在其之前的所有xxx.log都不能寫入,通常我們將最後一個LogSegment稱為
activeSegment
,之後追加的訊息將寫入activeSegment
,當其大小達到一定程度時就會重新生成一個新的activeSegment的.log
檔案。為了方便日誌分段檔案檢索,每個LogSegment都有對應的標識(baseoffset)和索引檔案。
- .index(offset索引檔案,用來檢索offset)
- .timeindex(時間戳索引,用來檢索時間戳)
- baseoffset(該值代表每個segment檔案的資料的起始offset,如00000000000000133.log,那麼該分段的起始offset是133,如果上一個分段檔案為00000000000000000.log,那麼上個分段檔案中儲存了133條訊息)
還可能出現.delete,.cleaned,.swap,.txnindex,leader_ecpoch_checkpoint等檔案。
從更加巨集觀的角度來講,kafka的日誌目錄結構如下:
2 kafka日誌格式演變
從kafka-0.8x到目前的2.x版本已經經歷了3個大版本:V0,V1,V2
- V0:0.8x-0.10.0,不包括0.10.0
- V1:0.10.0到0.11.0版本之前,不包括0.11.0
- V2:0.11.0到如今
2.1 V0的訊息格式
上圖左邊的就是V0版本的Record格式,通常通過LOG_OVERHEAD
與RECORD_OVERHEAD
同時來描述一個訊息,右邊的Message Set是訊息容器,用於儲存訊息。
- crc32: crc32校驗值,作用範圍magic~value之間 (4B)
- magic: 訊息版本號,這裡是0 (1B)
- attributes:訊息屬性,0-3代表壓縮格式(1B)
- 0代表NONE
- 1代表GZIP
- 2代表SNAPPY
- 3代表LZO4(0.9x引入)
- key length代表key的長度(4B),如果為-1,代表key為null,是沒有設定key的
- key代表訊息的key
- value length代表value的長度(4B)
- value代表訊息
在V0版本中訊息的最小長度為 4 + 1 + 1 + 4 + 4 = 14B(byte),如果小於這個值那麼,那麼這個訊息就是一條破損的訊息而不被接收,我們可以使用kafka內部的工具類檢視置頂的segment檔案的RECORD_OVERHEAD_V0(訊息的最小值)資訊
./kafka-run-class.sh kafka.tools.DumpLogSegments --files /tmp/kafka-logs/topic1-0/00000000000033568928.log
>>>>>>
#這裡將會顯示starting offset、offset、position、isvalid、payloadsize、magic、compressCodec、crc、keysize資訊,當前演示版本為kafka-0.8.2.1
Starting offset : 33568928
offset: 33568928 position : 0 isvalid: true payloadsize: 5 magic: 0
compresscodec: NoCompressionCodec crc: 592888119 keysize : 3
2.2 V1的訊息格式
除了新引入了一個timestamp,magic=1,其它的都是與V0相同,timestamp的大小為8B,所以V1版本的最小訊息(RECORD_OVERHEAD_V1)為14+8=22B(byte)。
- 該timestamp欄位由broker端的引數
log.message.timestamp.type
指定,預設是生產者建立訊息的時間createTime; - 我們可以通過在建立ProducerRecord的時候進行指定,new ProducerRecord(,timestamp);
- 如果沒有顯式手動指定timestamp,那麼就會選擇time.milliseconds();
- V1與V0一樣,都是通過LOG_OVERHEAD與RECORD_OVERHEAD來描述一個message。
2.3 V2的訊息格式
V2版本的訊息集從Message Set變成了Record Batch,這是一個處理批量訊息讀寫的NIO 通道channel,在訊息壓縮的過中,Record Batch Header部分是不會被壓縮的(也就是下圖中first offset到records count部分),被壓縮的是records欄位中的所有內容,每個Records中包含一條或多條Record。
- Record Batch對應Producer client中的Producerbatch
- Record對應Producer Record中的ProducerRecord
V2版本的Record格式去除了crc,將其移動到了RECORDBATCH,另外增加了length、timestamp delta 、offset delta;key、key length、value、value length還是與V0,V1保持一致,具體的新增的欄位如下。
- length:訊息的總長度;
- attributes:欄位在V2中雖然沒被使用,但是任然為其保留1B的空間,保證可擴充套件;
- timestamp delta:時間戳增量,是當前訊息的時間戳與RecordBatch的起始時間戳的差值,通常儲存一個時間戳需要8個位元組,這裡儲存的差值進一步減少了儲存的消耗;
- offset delta:位移增量,如果資料條目特別多,那麼儲存offset也是需要較多的儲存,這裡儲存的是當前訊息的offset與RecordBatch起始offset的差值,進一步節省儲存空間;
- headers:用來儲存應用級別的擴充套件。
除了對RECORD本身做了修改,在V2版本還對RECORDBATCH進行了徹底的修改,除了對上面的crc校驗,同時還新增瞭如下欄位。
- first offset:這個RECORBATCH的起始位移
- length:從partition leader epoch欄位到末尾的總長度,並不是訊息的總長度
- partition leader epoch:可以看作leader的版本號,或者看作分割槽leader的更新次數
- magic: 訊息格式的版本號
- attributes:訊息屬性,0~3位依舊是壓縮型別
- last offset delta :RECORDBATCH中的最後一個RECORD的offset與first offset的差值(增量)
- first timestamp:第一條訊息的時間戳
- producer id:生產者id:PID,用來與first sequence一起保證單個生產者-分割槽-單個session的冪等性
- producer epoch:與producer id一樣,用來支援事物與冪等(遞增序列)
- first sequence:與producer id,producer epoch一樣,用來保證事物與冪等(遞增序列)
- records count:該RECORDBATCH中RECORD的條目數
2.4 訊息壓縮
訊息越多壓縮的效果越明顯,資料比較少的時候選擇壓縮反而不太好,通常kafka的訊息在生產者這裡就開始選擇壓縮,在Broker上也是以壓縮的形式進行儲存的,只有在消費資料處理資料的術後才會將訊息進行解壓,這樣就保證了端到端的壓縮。在kafka的引數中,壓縮格式通過compress.type
來指定,預設為producer
,表示保留生產者使用的壓縮方式,還可以選擇lz4,snappy,gzip
等配置,分別表示使用LZ4,SNAPPY,GZIP
的壓縮演算法
注:壓縮率 = 壓縮後大小 /壓縮前大小 * 100%,壓縮率通常是越小越好
,而口語中常說壓縮率越高越好。
kafka中有 2個概念,不能混淆
- compress message 使用壓縮演算法將訊息進行壓縮,減少記憶體,網路io,與磁碟的消耗
- compact message 將日誌中的訊息進行清理,類似於hbase的compact操作
訊息的壓縮是針對整個訊息集RECORDBATCH(MESSAGE SET),將整個訊息集壓縮成wrapper message 和inner message,如下圖
該途中offset為RECORDBATCH的first offset,內層訊息中的offset為每個 record的offset與外層offset的增量,即(x - first offset)。
相關文章
- Impala之儲存和壓縮
- Android 程式設計日誌之資料儲存Android程式設計
- Redis儲存優化--小物件壓縮Redis優化物件
- CSS單行格式化與壓縮CSS
- linux _壓縮日誌Linux
- 浪潮線上壓縮,為資料儲存降本增效
- Flutter持久化儲存之資料庫儲存Flutter持久化資料庫
- Hive的壓縮儲存和簡單優化Hive優化
- 濃縮的才是精華:淺析GIF格式圖片的儲存和壓縮
- CQRS 儲存事件與日誌記錄事件
- Linux下常用壓縮格式的壓縮與解壓方法Linux
- 壓縮SQL SERVER日誌程式碼SQLServer
- mysql 資料儲存檔案及6類日誌MySql
- SQL Server資料庫事務日誌儲存序列SQLServer資料庫
- 8-字串的壓縮儲存字串
- Hive之儲存格式Hive
- 【儲存管理】日誌管理
- MySQL 壓縮二進位制日誌MySql
- Sql Server 2005 日誌壓縮SQLServer
- 使用logrotate來壓縮日誌(轉)logrotate
- Linux下常用壓縮格式的壓縮與解壓方法---轉載Linux
- 物件儲存服務的壓縮特性物件
- Java實現檔案壓縮與解壓[zip格式,gzip格式]Java
- 如何在HDFS中進行資料壓縮以實現高效儲存?
- redis-5.資料儲存格式Redis
- 超酷演算法:日誌結構化儲存演算法
- unix和linux下常用壓縮格式的壓縮與解壓方法(轉)Linux
- linux 下壓縮與解壓資料夾Linux
- 監控影片儲存壓縮解決方案
- lumen cli日誌和普通日誌分開儲存
- 【shell】用shell實現自動壓縮日誌並且清理壓縮包
- android解壓縮GZIP格式的網頁資料Android網頁
- 序列化資料傳輸壓縮
- Hive之 資料儲存Hive
- oralce 壓縮表與heap表儲存空間與查詢效能比較
- 日誌服務之資料清洗與入湖
- python日誌怎麼儲存Python
- Myisam 靜態格式資料儲存結構