放弃JSON吧!这4种数据格式让API性能提升5倍
哎我跟你说…我这两天真是被一个接口折腾到脑袋嗡嗡的。昨天晚上十一点多,我在公司楼下啃着个凉掉的肉夹馍,手机那边小李给我发消息:“东哥你看下,这个接口怎么又慢成狗了?JSON 是不是又搞事了?”我当时就想…哎这玩意我不是早就说过嘛,JSON 好用是好用,但真不是高性能场景里的亲儿子。
我边吃边跟他说,你别老迷信 JSON,尤其是那种几十万条字段来回跑的,序列化反序列化每次都能把 CPU 打一个激灵。就在那会儿的风吹脸上,肉夹馍渣掉我鞋子上,我突然想起来前阵子做接口压测的时候几种数据格式差了好几倍,于是我今天就随手跟你们唠一下,真的,不吹不黑,JSON 在性能面前就是个老实孩子。
你看我昨天在工位上写代码的时候…突然想到四种替代 JSON 的方案,顺手跑了下压测
我当时是在搞一个设备日志同步的活儿,那日志一条几十 K 的、动不动就是万条级别。我用 JSON 处理的时候 CPU 直接顶满,风扇跟飞机起飞一样。我当时就愣了下,手敲了一段最普通的 Python 转 JSON 的代码:
import jsondefto_json(data):
return json.dumps(data)
跑个几万条数据直接让我笔记本变暖手宝…那一瞬间我脑子里“哗”一下就想起之前测过的另外几种格式。
1. MessagePack:像 JSON,但压缩得狠
我记得当时是凌晨一点多吧,我们组那个小王突然跑过来说:“东哥你那个 JSON 压测数据能借我跑跑嘛?”我说你别跑 JSON 了,换 MessagePack 吧。
MessagePack 长得跟 JSON 差不多,但它是二进制的,序列化直接快飞起。
当时随手写了个 demo:
import msgpackdata = {"user": "east", "age": 33, "tags": ["dev", "python"]}
packed = msgpack.packb(data)
unpacked = msgpack.unpackb(packed)
小王测着测着就喊:“卧槽东哥这比 JSON 快三四倍啊!”
我回头说:“正常…你别激动。”
这玩意对高并发、IO 压力大的接口来说真的是香。
2. Protobuf:谷歌亲儿子,就是麻烦点
说实话…我前天在地铁上还在琢磨 Protobuf 的 schema 要不要扩字段又不破坏兼容性。Protobuf 最大的问题就是麻烦,你得写 .proto 文件,而且字段类型都要先定义好。
但性能真的是强,序列化反序列化简直飞。
简单举个例子:
syntax = "proto3";message User {
string username = 1;
int32 age = 2;
}
Python 调用的时候:
user = User(username="east", age=33)
binary_data = user.SerializeToString()
速度是 JSON 的 5~10 倍,我当时压测的时候那曲线是真好看。
3. Avro:动态 schema 的狠角色
这个我是在公司楼下抽烟时碰到做大数据那帮兄弟,他们说 Kafka 里面大量用 Avro,因为 Avro 支持 schema evolution,不像 Protobuf 那么死板。
我那会硬是被他们拉着看了个 demo:
import avro.schema
import avro.io
import io
性能比 JSON 好一大截,而且适合需要不断变更结构但又想保持高性能的场景,比如日志、埋点。
我抽烟抽到一半直接说:“行了行了,这玩意我回去也加到我的工具链里。”
4. FlatBuffers:不用反序列化,直接读
这个是真狠。
我记得我第一次测试 FlatBuffers 是凌晨三点,因为一个设备通信接口慢得离谱,JSON 处理大字典直接把 CPU 干爆。后来我试了 FlatBuffers…序列化几乎是零成本,数据还能像数组一样随机访问。
像这样:
# 实际 FlatBuffers 要用 flatc 生成代码
# 使用起来类似:
user = User.GetRootAsUser(buf, 0)
name = user.Name()
就是不用反序列化,直接“读”。这个特性让它在游戏行业、物联网设备里特别受欢迎。
反正那天我跟小李说完以后他沉默了三秒,然后说:
“那东哥,我是不是得把我们项目所有 JSON 全换掉?”
我当时嘴里还在嚼凉掉的肉夹馍,我说:
“不是换掉,是别在高频 IO、超大 payload、低延迟要求的接口里用 JSON…它承受不来。”
你看一般我建议是:
| Protobuf / FlatBuffers | |
| Avro | |
| MessagePack | |
| JSON 继续用 |
我现在写到这又想起小王昨天跑来问我 MessagePack 怎么处理日期格式,我当时正热着外卖没空搭理他…算了我等下回他去。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html
虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB