Kafka版本
- kafka版本1.1.1,可能絕大部分也適用於kafka 0.10.x及以上版本。
消息格式
- 目前Kafka消息格式有三個版本,V0、V1和V2。
V0版本
-
V0版本主要是指Kafka0.10.0.0之前的版本,是kafka最早的消息版本
-
字段含義
- CRC(4B):CRC校驗碼,佔用4個字節,校驗magic至value之間字節是否被篡改
- magic(1B):消息格式版本號,佔用1個字節。V0版本是0,V1版本是1,V2版本是2
- attributes(1B):屬性字段,佔用1個字節,只使用低3位表示消息的壓縮類型,其他5位是保留位。
- 0表示NONE,表示不啓用壓縮
- 1表示GZIP
- 2表示SNAPPY
- 3表示LZ4
- key length(4B):表示消息的key的長度。如果爲-1,則表示沒有設置key,即key=null
- key:消息key,長度由key length值指定。如果key length值是-1,則無key(沒有此字段)
- value length(4B):表示消息的長度,佔用4字節。
- value:消息value,長度由value length值指定。如果value length值是-1,則無value,消息沒有該字段。
-
消息頭部(message Header):除了Key和Value之外的所有字段統稱爲消息頭部。總共佔用14字節(4B+1B+1B+4B+4B),即V0版本的消息長度最小是14B
-
此版本的問題
- 即使不指定key(即key length=-1),還是要佔用4個字節的空間
- 即使不指定value(即value length=-1),還是要佔用4個字節的空間
- 沒有消息的時間信息。kafka定期刪除過期log只能依靠文件的最後修改時間。文件系統最後的修改時間很容易受到外部不確定因素的干擾。
V1版本
-
V1版本主要是[0.10.0.0,0.11.0.0)之間的版本
-
V1與V0的主要差異
- 引入了8B的時間戳,即V1版本的消息頭部最小是22B(14B+8B)
- 屬性字段第4位被用於指定時間戳類型
- 0表示timestamp類型爲
CREATE_TIME
,CREATE_TIME
表示在消息創建時由producer指定的時間戳 - 1表示timestamp類型爲
LOG_APPEND_TIME
。LOG_APPEND_TIME
表示消息被髮送到broker端時由broker指定的時間戳。
- 0表示timestamp類型爲
Message Set
-
Kafka的消息層次分爲:消息集合(message set)和消息。V0和V1版本使用的是日誌項(log entry),以下是日誌項的格式
-
每個消息集合中的日誌項由shallow message和log entry header組成
- shallow message:如果沒有啓用消息壓縮,那麼shallow message就是這條消息本身。如果啓用消息壓縮,kafka會將多條消息壓縮到一起統一封裝成shallow message的value字段。此時該shallow message被稱爲wrapper消息(或者外部消息),而value字段中包含的消息則被稱爲inner消息(內部消息)。v0和v1版本中的日誌項只能包含一條shallow message
- log entry header(日誌項頭部):由8B的offset和4B的size組成。offset指該消息在分區日誌中的offset,如果是未壓縮的消息,該offset就是消息的offset,否則該字段表示wrapper消息中最後一條inner消息的offset。因此,從V0、V1版本消息集合日誌項中搜索該日誌項的起始偏移是非常困難的,需要遍歷所有的inner消息,即broker需要解壓縮操作。
V0與V1的缺陷
- 空間利用率不高:不論key和value長度是多少,總是固定佔用4B
- 只保存最新消息偏移量:如果啓用壓縮,offset是消息集合中最後一條消息的offset。如果想要獲取第1條消息的offset,必須解壓所有消息並加載到內存中,然後反向遍歷才能獲取到
- CRC校驗,爲每條消息都執行CRC沒有必要
- 未保存消息長度:每次需要單條消息的總字節數信息時都需要計算得出,沒有使用單獨字段來保存。每次計算時爲了避免對現有數據結構的破壞,都需要大量的對象副本, 解序列化效率很低。
V2版本
-
V1版本主要是0.11.0.0(包含)之後的版本。此版本相比於v0和v1改動很大,引入了變長整型(Varints)和ZigZag編碼(借鑑ProtoBuffer中的Zig-zag編碼方式,絕對值較小的整數佔用比較少的字節)。Varints是使用一個或多個字節來序列化整數的一種方法,數值越小,其所佔用的字節數就越少。Zig-zag編碼方式,使得絕對值較小的整數佔用比較少的字節
-
字段詳解
- 增加消息總長度字段
- 可變時間戳,使用一個可變長度保存與batch起始時間戳的差值。差值一般很小,所以需要保存的字節也小
- 增加offset,保存消息offset與外層batch起始offset的差值,節省消息總字節數
- 增加消息headers,主要是爲了滿足用戶定製化需求,用戶手動設置的
- 去除CRC校驗,V2不再爲每條消息計算CRC32值,而是對整個消息batch進行CRC校驗
- 廢棄attribute字段。V2版本將原先保存在attribute字段中的壓縮類型、時間戳等信息統一保存在外層batch格式字段中,但是依然保留了單字節attribute爲了以後擴展使用。
-
V2版本中消息集合(message set)被消息批次所取代,叫做RecordBatch。這裏的RecordBatch與producer中的batch不是一個含義。
-
bath字段詳解
-
CRC被放入Batch
-
增加2B的attribute。
-
最低3位依然是壓縮類型
-
第4位保存時間戳類型(NO_TIMESTAMP_TYPE是-1,CREATE_TIME是0,LOG_APPEND_TIME是1)。
-
第5位事務類型(事務消息是1,非事務消息是0)
-
第6位控制類型(ABORT是0,COMMIT是1,UNKNOWN是-1)
-
-
PID、 producer epoch 和序列號等信息都是 0.11.0.0 版本爲了實現冪等性 producer 和支持事務而引入的。Kafka依靠
PID+epoch
來辨別消息是否己成功提交,從而防止出現重複生產消息。
-
-
0.11.0.0版本(及以後)的 Kafka消息在支持事務、幕等性 producer的同時還在一定程度上減少了網絡I/O和磁盤 I/O 的開銷(因V2版本協議的緣故)