Protobuf序列化原理学习

Protobuf 序列化原理学习

1. 基本概念

  • 消息:由于Protocp Buffer主要用于数据存储、网络通信的场景,将结构化的数据(数据结构或对象)进行序列化,生成二进制串来保存或传输。把要序列化的结构化数据称为**消息**。

  • T - L - V 的数据存储方式:即 Tag - Length - Value标识 - 长度 - 字段值 存储方式。以 标识 - 长度 - 字段值 表示单个数据,最终将所有数据拼接成一个字节流。

  • T - V的数据存储方式:即 Tag - Value标识 - 字段值 存储方式。VarintZigzag 编码后的格式就是这种,不需要记录长度,每个字节的最高位去记录下一个字节是否属于当前数字。

2. 三个结论

  • 结论1Protocol Buffer将消息中的每个字段进行编码,然后利用T - L - V存储方式对数据进行存储,最终得到一个二进制字节流。

  • 结论2Protocol Buffer对于不同数据类型采用不同的序列化方式(编码方式 & 数据存储方式)

在这里插入图片描述

  • 对于存储Varint编码数据,就不需要存储字节长度 Length,所以实际上Protocol Buffer的存储方式是 T - V

  • Protocol Buffer采用其他编码方式(如LENGTH_DELIMITED)则采用T - L - V

  • 结论3:因为 Protocol Buffer对于数据字段值的 独特编码方式 & T - L - V数据存储方式,使得 Protocol Buffer序列化后数据量体积如此小

3. 编码方式

3.1 Varint 编码

  • 定义:一种变长的编码方式
  • 原理:用字节表示数字:值越小的数字,使用越少的字节数表示
  • 作用:通过减少表示数字的字节数从而进行数据压缩

如:

  • 对于 int32 类型的数字,一般需要 4个字节 表示;
  • 若采用 Varint编码,对于很小的 int32 类型 数字,则可以用 1个字节 来表示
  • 虽然大的数字会需要 5 个 字节 来表示,但大多数情况下,消息都不会有很大的数字,所以采用 Varint方法总是可以用更少的字节数来表示数字

Varint 编码的不足:

在计算机内,负数一般会被表示为很大的整数。(因为计算机定义负数的符号位为数字的最高位

因此,使用**Varint** 编码负数一定需要5个bytes。

解决方案: Protocol Buffer 定义了 sint32 / sint64 类型表示负数,先使用 Zigzag 编码(将 有符号数 转换成 无符号数),再采用 Varint编码,从而用于减少编码后的字节数。

3.2 Zigzag 编码

  • 定义:一种变长的编码方式

  • 原理:使用 无符号数 来表示 有符号数字;

  • 作用:使得绝对值小的数字都可以采用较少字节来表示;

  • Zigzag 编码 是补充 Varint编码在 表示负数 的不足,从而更好的帮助 Protocol Buffer进行数据的压缩

  • 所以,如果提前预知字段值是可能取负数的时候,记得采用sint32 / sint64 数据类型

  1. 对于int32 / int64 类型的字段值(正数),Protocol Buffer直接采用 Varint编码
  2. 对于sint32 / sint64 类型的字段值(负数),Protocol Buffer会先采用 Zigzag 编码,再采用 Varint编码

参考文献

摘抄搬运自:

Protocol Buffer 序列化原理大揭秘 - 为什么Protocol Buffer性能这么好?_flowbuf 的序列化价值-CSDN博客

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值