一起讀《資料密集型應用系統設計》之:Thrift和Protobuf格式分析

一起讀《資料密集型應用系統設計》之:Thrift和Protobuf格式分析

概述

Apache Thrift和Protocol Buffers(protobuf)是兩種功能類似的二進位制編碼協議。Protocol Buffers最初由Google開發,而Thrift則由Facebook開發。它們都在2007-08年進行了開源。

Protobuf和Thrift都需要事先定義好schema。對於Thrift,它的schema用Thrift IDL(Interface definition language)來描述,例如:

struct Person { 1: required string userName, 2: optional i64 favoriteNumber, 3: optional list interests}

相同的schema在Protobuf中的定義很像:

message Person { required string user_name = 1; optional int64 favorite_number = 2; repeated string interests = 3;}

Thrift和Protobuf都有各自的程式碼生成工具,用來生成給定schema在不同語言中的類程式碼。應用程式可以透過這些自動生成的程式碼對資料進行編碼或者解碼。

二進位制編碼格式

Thrift有兩種不同的二進位制編碼格式,分別叫做BinaryProtocol和CompactProtocol。先來看BinaryProtocol,我們以這樣一段資料為例:

{ “userName”: “Martin”, “favoriteNumber”: 1337, “interests”: [“daydreaming”, “hacking”]}

它在編碼後的資料格式如下所示:

一起讀《資料密集型應用系統設計》之:Thrift和Protobuf格式分析

在這種格式中,每一個欄位都會有其對應的型別和欄位的長度。字串以ASCII編碼儲存在data中。

值得注意的是,在這種格式中沒有儲存欄位的名字。每一個欄位都用一個整數來標識。這些整數標識在schema中被指定。

另一種格式CompactProtocol在語法上與BinaryProtocol是等價的。具體格式如下:

一起讀《資料密集型應用系統設計》之:Thrift和Protobuf格式分析

與BinaryProtocol的例子相比,相同內容的CompactProtoco版本僅佔用34個位元組。其原因在於它把欄位型別與欄位標識合併到一個位元組裡。並且透過使用可變長整數,從而實現用兩個位元組來儲存原本需要8個位元組的1337。其中,每一個位元組的最高位用來標識是否還需要更多的位元組。

最後一個例子,Protobuf的位元組格式跟Thrift CompactProtocol非常相似,只需要33個位元組

一起讀《資料密集型應用系統設計》之:Thrift和Protobuf格式分析

需要注意的是,schema中每個欄位是required或者是optional的資訊並不儲存在二進位制編碼中,而是在runtime時進行檢查。

(End)