Python技术迷

放弃JSON吧!这4种数据格式让API性能提升5倍

哎我跟你说…我这两天真是被一个接口折腾到脑袋嗡嗡的。昨天晚上十一点多,我在公司楼下啃着个凉掉的肉夹馍,手机那边小李给我发消息:“东哥你看下,这个接口怎么又慢成狗了?JSON 是不是又搞事了?”我当时就想…哎这玩意我不是早就说过嘛,JSON 好用是好用,但真不是高性能场景里的亲儿子。

我边吃边跟他说,你别老迷信 JSON,尤其是那种几十万条字段来回跑的,序列化反序列化每次都能把 CPU 打一个激灵。就在那会儿的风吹脸上,肉夹馍渣掉我鞋子上,我突然想起来前阵子做接口压测的时候几种数据格式差了好几倍,于是我今天就随手跟你们唠一下,真的,不吹不黑,JSON 在性能面前就是个老实孩子。

你看我昨天在工位上写代码的时候…突然想到四种替代 JSON 的方案,顺手跑了下压测

我当时是在搞一个设备日志同步的活儿,那日志一条几十 K 的、动不动就是万条级别。我用 JSON 处理的时候 CPU 直接顶满,风扇跟飞机起飞一样。我当时就愣了下,手敲了一段最普通的 Python 转 JSON 的代码:

import json

defto_json(data):
return json.dumps(data)

跑个几万条数据直接让我笔记本变暖手宝…那一瞬间我脑子里“哗”一下就想起之前测过的另外几种格式。

1. MessagePack:像 JSON,但压缩得狠

我记得当时是凌晨一点多吧,我们组那个小王突然跑过来说:“东哥你那个 JSON 压测数据能借我跑跑嘛?”我说你别跑 JSON 了,换 MessagePack 吧。

MessagePack 长得跟 JSON 差不多,但它是二进制的,序列化直接快飞起。

当时随手写了个 demo:

import msgpack

data = {"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
需要灵活 schema 又要高性能
Avro
想保持 JSON 的轻松但又要快
MessagePack
轻量接口、内部工具、不追求极限性能
JSON 继续用

我现在写到这又想起小王昨天跑来问我 MessagePack 怎么处理日期格式,我当时正热着外卖没空搭理他…算了我等下回他去。

-END-

我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

🔥虎哥私藏精品🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB