序列化格式 (JSON / Protobuf / Avro / Thrift)

★★★★Reviewed

FromDDIA

📚 From the Books

序列化格式 (JSON / Protobuf / Avro / Thrift)Encoding & Evolution

序列化是把記憶體中的物件變成可傳輸 / 可儲存的 bytes(encoding),再還原回來(decoding)。選格式的本質是在問:要人讀得懂,還是要機器跑得快、傳得省

🧠 Intuition

TIP

一句話分辨:文字格式把「欄位名」也一起塞進每一筆資料;二進位 schema 格式把欄位名抽成外部 schema,資料裡只剩值(甚至連 tag 都省)。膨脹與效率的差別,幾乎都來自「欄位名要不要重複攜帶」。

⚖️ Tradeoffs

文字格式 — 可讀性換體積與精度
  • JSON / XML 自帶結構、debug 友善、瀏覽器與工具鏈原生支援。
  • 缺點:欄位名重複攜帶造成膨脹;數字精度不明(JSON 無區分整數/浮點,大整數會被 JS 截斷);二進位資料只能 Base64(再膨脹 33%)。
  • 適合對外 API、設定檔、log——可讀性的價值大於效率。
Thrift / Protobuf — 用 field tag 對齊
  • schema 給每個欄位一個數字 field tag,encoded bytes 裡存的是 tag + 型別 + 值,不存欄位名
  • 相容性靠 tag 維繫:改欄位名沒差(tag 不變),但 tag 一旦用過就不能改用途。
  • Protobuf 用 varint 等緊湊編碼,體積通常比 JSON 小數倍;兩者都需先 compile schema 產 stub。
Avro — writer/reader schema,無 tag
  • 最精簡:encoded bytes 裡只有值,連 field tag 都沒有,靠順序對齊。
  • 解碼時需同時拿到 writer schema(寫入時用的)與 reader schema(讀取時期望的),由 schema resolution 對齊兩者差異。
  • 特別適合大檔案 / 資料倉儲(Hadoop、Kafka + Schema Registry):schema 只在檔頭存一次,動態產生的 schema 也好處理。
效率與體積對比
  • 體積:Avro ≈ Protobuf < Thrift < 二進位 XML << JSON < XML(粗略順序,視資料而定)。
  • CPU:二進位格式編解碼遠快於 JSON 字串解析。
  • 代價:二進位格式不可直接肉眼讀,debug 需工具;schema 成為必須管理的 artifact。

🔑 Takeaways

✍️ My Notes

2026-07-01

  • Q: Protobuf 用 tag、Avro 不用 tag,差在哪?為什麼 Avro 還能演化?
  • A: Protobuf 靠「tag 不變」來辨識欄位,所以你能自由增刪欄位、改名,只要 tag 不重用。Avro 沒 tag、純靠順序,乍看很脆,但它的 schema resolution 會在解碼時用欄位名把 writer schema 與 reader schema 對齊:reader 有而 writer 沒有的欄位用預設值補,writer 有而 reader 沒有的欄位直接略過。代價是你必須知道 writer schema(所以要 Schema Registry 或檔頭內嵌),這也正是 Avro 在「大量同 schema 記錄」場景最省的原因——schema 不必每筆攜帶。

📖 Further Reading

🔗 Dive Deeper