协议交互与信息缓存时JSON一定是最优解吗,浅析msgp protobuf flatbuffers sbe json

33 阅读5分钟

0x00 概述

先说结论:不是,不同的场景有不同的最佳选择。

介于json良好的可读性和适中的时空性能,在多数协议设计和信息缓存时候被无脑选择使用,对于性能不敏感的业务场景而言,这完全没有问题。 但是一些对于性能敏感的场景,或者内存缓存场景而言,json的选用则需要谨慎的评估考量。

接下来我们从通用数据到实例测试来看一下几种数据格式的差异对比。

0x01核心特性对比

1. MessagePack (msgp)

  • 类型: 二进制JSON
  • Schema: 无需schema
  • 特点: 比JSON更紧凑的二进制格式

2. Protocol Buffers (protobuf)

  • 类型: 二进制序列化
  • Schema: 需要.proto文件定义
  • 特点: Google出品,成熟稳定

3. FlatBuffers

  • 类型: 零拷贝二进制
  • Schema: 需要.fbs文件定义
  • 特点: 无需反序列化即可访问

4. Simple Binary Encoding (SBE)

  • 类型: 零拷贝二进制
  • Schema: 需要XML schema
  • 特点: 为金融交易设计,极致性能

5. JSON

  • 类型: 文本格式
  • Schema: 无需schema
  • 特点: 人类可读,广泛支持

0x02 性能对比

序列化速度排名

1. SBE          ⚡⚡⚡⚡⚡ (最快,通常<100ns)
2. FlatBuffers  ⚡⚡⚡⚡  (接近SBE,零拷贝)
3. msgp         ⚡⚡⚡   (比JSON快5-10倍)
4. Protobuf     ⚡⚡⚡   (与msgp相近)
5. JSON         ⚡     (最慢,需要字符串解析)

反序列化速度排名

1. FlatBuffers  ⚡⚡⚡⚡⚡ (零拷贝,无需反序列化)
2. SBE          ⚡⚡⚡⚡⚡ (零拷贝)
3. msgp         ⚡⚡⚡
4. Protobuf     ⚡⚡
5. JSON         ⚡

实测数据参考(1MB数据):

  • SBE: 序列化 ~0.05ms,反序列化 ~0.01ms
  • FlatBuffers: 序列化 ~0.1ms,反序列化 ~0.001ms
  • msgp: 序列化 ~1ms,反序列化 ~2ms
  • Protobuf: 序列化 ~2ms,反序列化 ~3ms
  • JSON: 序列化 ~10ms,反序列化 ~15ms

0x03 空间成本对比

以一个典型的用户对象为例:

json

{
  "id": 123456789,
  "name": "张三",
  "email": "zhangsan@example.com",
  "age": 28,
  "balance": 1234.56,
  "tags": ["vip", "active"]
}

数据大小对比

JSON:         ~150 bytes  (100%)
msgp:         ~95 bytes   (63%)
Protobuf:     ~85 bytes   (57%)
FlatBuffers:  ~120 bytes  (80%) - 包含偏移表
SBE:          ~75 bytes   (50%)

压缩效率

格式          原始    +gzip   +zstd
JSON          100%    40%     35%
msgp          63%     45%     40%
Protobuf      57%     42%     38%
FlatBuffers   80%     55%     50%
SBE           50%     43%     39%

四、详细优劣势分析

SBE (Simple Binary Encoding)

优势:

  • 极致的性能,专为低延迟设计
  • 零拷贝,零内存分配
  • 可预测的内存布局
  • CPU缓存友好

劣势:

  • 学习曲线陡峭
  • 生态系统较小
  • Schema演进困难
  • 主要支持C++/Java

🎯 适用场景: 高频交易、实时竞价、游戏服务器


FlatBuffers

优势:

  • 零拷贝访问,无需完整反序列化
  • 内存高效
  • 支持随机访问
  • 向后/向前兼容性好

劣势:

  • 序列化后体积略大(因为偏移表)
  • 写入性能略低于读取
  • API相对复杂

🎯 适用场景: 游戏开发、移动应用、嵌入式系统


MessagePack (msgp)

优势:

  • 无需schema,开发快速
  • 比JSON小且快
  • 多语言支持好
  • 易于调试(与JSON类似)

劣势:

  • 性能不如schema-based方案
  • 无类型安全
  • 无版本控制机制

🎯 适用场景: 微服务通信、缓存、日志存储


Protocol Buffers

优势:

  • 成熟稳定,生态系统完善
  • 强类型安全
  • 优秀的向后兼容性
  • gRPC原生支持

劣势:

  • 需要代码生成
  • 反序列化需要完整解析
  • 性能不如SBE/FlatBuffers

🎯 适用场景: 微服务RPC、API通信、数据存储


JSON

优势:

  • 人类可读,易于调试
  • 无需工具链
  • 浏览器原生支持
  • 生态系统最完善

劣势:

  • 体积大(字段名重复)
  • 解析慢(字符串处理)
  • 类型不安全("1" vs 1)
  • CPU和内存开销大

🎯 适用场景: Web API、配置文件、开发调试

0x04 实测对比

结合后端批量数据缓存需求,实测几种协议格式的解码性能和缓存与传输空间消耗。

源码地址 github.com/TeleMiniGam…

测试结果如下:

================================ Wire Decode Benchmark ================================
Date: 2025-10-15T13:14:40+08:00 | Go: go1.25.2 | GOMAXPROCS=14 | N=1000 items
---------------------------------------------------------------------------------------
Payload Sizes:
  - msgp       : total=  614594 B  avg=614.6 B/item  gzip=   37510 B
  - protobuf   : total=  437594 B  avg=437.6 B/item  gzip=   34043 B
  - flatbuffers: total=  621164 B  avg=621.2 B/item  gzip=   41521 B
  - sbe        : total=  468594 B  avg=468.6 B/item  gzip=   35724 B
  - json       : total=  710594 B  avg=710.6 B/item  gzip=   39157 B
---------------------------------------------------------------------------------------
Codec         Decode once (ns/item)  Decode x1000 (ns/item)  Note
flatbuffers   374.6               363.1
sbe           478.3               458.2
msgp          515.4               274.0
protobuf      577.0               558.5
json          4616.1              4492.7
---------------------------------------------------------------------------------------
* Decode once:每个元素只解码 1 次;Decode x1000:每个元素在同一字节切片上重复解码 1000 次(考察热点路径/复用缓存的吞吐上限)。
* gzip 为整包压缩后的大小,仅作带宽估算参考。
=======================================================================================

很显然能看到几个情况:

  • flatbuffers的解码性能是最高的,当然空间占用也相对较大,仅次于json。
  • 无论协议格式是什么类型,在传输层的表现差异不明显,因为gzip之后大小都差不多。

0x05 小结

JSON绝不是最优解,它只是在开发便利性和广泛支持上占优。选择序列化协议应该基于:

  1. 性能要求: 延迟<1ms → SBE/FlatBuffers
  2. 开发效率: 快速迭代 → JSON/msgp
  3. 兼容性: 长期存储 → Protobuf
  4. 生态系统: 多语言 → Protobuf/JSON
  5. 数据规模: 大数据量 → 二进制格式

黄金法则: 对外JSON保持兼容,对内二进制追求性能。

实际生产中我们应该结合需要采用混合方案,例如:

  • 外部API (JSON)
  • API Gateway (JSON)
  • 内部RPC (Protobuf/gRPC)
  • 缓存层 (msgp/FlatBuffers)
  • 热路径优化/极致性能优化 (SBE/零拷贝)
  • 持久化 (Database/Protobuf)