推荐系统中Redis 数据存储:二进制序列化协议选型与优化
背景
Java 实现的推荐系统需将核心数据(用户画像、商品特征)存储进 Redis,供实时推荐接口查询。推荐数据中包含、用户行为序列、商品属性集合,导致单条数据占用 Redis 磁盘 / 内存空间较大。目前采用 JSON(FastJSON)文本序列化协议,虽可读性强,但存在序列化性能低、数据体积大、内存占用高的问题,需探索适配推荐系统的二进制序列化协议,寻找最优数据存储方案。
新的序列化方案需要满足以下核心需求:
- 跨语言支持:数据需要被Java实时推荐服务和Python离线训练系统共同使用
- 高性能:序列化/反序列化速度快,数据体积小
- 高灵活性:能够支持推荐系统特征的快速迭代和schema演化
- 生产环境友好:稳定性高,兼容性好,工具链完善
一、候选方案分析
1.1 Protocol Buffers (Protobuf)
优势:
- 性能优异,序列化速度比JSON快3倍以上
- 数据体积紧凑,比JSON节省60%空间
- 强类型schema定义,支持向前向后兼容
- 官方支持多种语言(Java, Python, C++, Go等)
劣势:
- 需要预定义.proto schema文件
- 二进制数据不可直接阅读,调试较复杂
1.2 Kryo
优势:
- Java环境下性能极佳(序列化速度比JSON快5倍)
- 无需预定义schema,使用简单
- 支持复杂对象图形和循环引用
劣势:
- 仅支持Java生态系统,无法跨语言使用
- 版本兼容性较差,schema演化困难
- 存在一定的安全风险
1.3 FST (Fast Serialization)
优势:
- 性能接近Kryo但稳定性更好
- 支持增量序列化,适合更新频繁的场景
- 内存占用低,GC压力小
劣势:
- 社区活跃度较低,遇到问题难解决
- 主要面向Java生态,跨语言支持有限
1.4 MessagePack
优势:
- 跨语言支持好(若推荐系统后续对接 Python 离线模块可复用)
- 性能优秀,序列化速度优于 JSON
- 数据格式紧凑,支持流式处理(推荐系统批量加载数据场景适配)
- 无需预定义 schema,开发效率高
劣势:
- 在 Java 环境中性能不如 Kryo/FST,推荐系统高并发接口响应速度受影响
- 对复杂对象支持有限,易出现序列化异常
1.5 Hessian
优势:
- 内部已有使用经验,团队上手成本低
- 性能较好,支持推荐系统复杂对象
- 网络传输友好,适配推荐系统 “Redis 远程调用” 场景
劣势:
- 性能不如 Kryo/FST,推荐系统高并发时序列化瓶颈明显
- 数据体积相对较大,比 Kryo 多占用 20-30% 空间,Redis 内存利用率低
性能测试
2.1 测试数据(模拟推荐系统核心数据)
- 取出一批用户的原始特征数据进行并发测试
- 并发测试:模拟推荐接口 1000 个并发请求
2.2 测试结果(以 JSON 为基准)
序列化协议 | 序列化时间 (ms) | 反序列化时间 (ms) | 数据大小 (KB) | 压缩率 | 内存占用 (MB) |
JSON (FastJSON) | 基准(1.0x) | 基准(1.0x) | 基准(1.0x) | 基准(0%) | 基准(1.0x) |
Protobuf | 0.3x | 0.4x | 0.4x | 60% | 0.6x |
Kryo | 0.2x | 0.3x | 0.3x | 70% | 0.5x |
FST | 0.25x | 0.35x | 0.35x | 65% | 0.55x |
MessagePack | 0.5x | 0.6x | 0.6x | 40% | 0.8x |
Hessian | 0.6x | 0.7x | 0.7x | 30% | 0.9x |
三、推荐方案:Protobuf 优化
基于以上分析,我们推荐使用Protocol Buffers作为新的序列化方案,主要基于以下考虑:
- 性能与效率平衡:Protobuf在性能和资源使用上提供了最佳平衡点
- 跨语言支持:完美支持Java和Python双环境,满足实时服务和离线训练需求
- schema演化能力:强大的向前向后兼容性,适合快速迭代的推荐系统
- 工业级稳定性:经过大规模生产验证,工具链完善
- 长期可维护性:强类型schema提高了代码可维护性和团队协作效率