随着应用程序的升级,系统需要保持向后兼容(新代码读旧数据)和向前兼容(旧代码读新数据).数据的编码支持更好的兼容性尤为重要.
编码数据
序列化: 将内存中的数据编码成字节序列(才能通过网络发送)
反序列化: 将字节序列解码成内存中的数据
编程语言特定的编码
特定的编程语言内置了序列化的方法,例如java.io.Serializable
和pickle
,但是却与语言紧密相关,其他语言难以读取.
除非临时使用,采用语言内置编码通常是一个坏主意。
JSON XML和二进制变体
通常流行使用的编码有JSON
/XML
和CSV
.
二进制版本的JSON
(BJSON
等)和XML
(WBXML
)可以节省更多的空间.类似的还有Thrift
与Protocol Buffers
.
Thrift
与Protocal Buffers
如何保证数据的兼容?
编码的记录是编码字段的拼接.字段在
IDL
中由标签号码标识.即使更改字段名称,只要不更改标签号码,编码的数据就不会变更(编码的数据不会引用字段名称).如果新增了字段(使用新的标签号码),旧代码可以忽略该不能识别的字段 (添加的字段必须是可选的或者具有默认值),因此保证了向前兼容.而新代码仍然可以读取旧数据.删除字段也只能删除非必填字段.
还有一种适用于Hadoop
的Avro
,因为不包含字段标签号,对动态生成的模式更加友好.如何保证数据的兼容?
它的IDL
包含写模式(编码到程序中, writer
)和读模式(程序解码, reader
).只需要根据正确的IDL
中的顺序进行解析,就可以正确解码.只要写模式和读模式是兼容的,Avro
可以通过查看写模式和读模式的定义进行转换(根据字段名匹配),所以这两者不必完全相同.
reader
如何知道数据是采用哪个writer
的模式编码的:
- 大文件情况下只要在每个文件开头包含一次作者模式.
- 独立数据库可以保存作者模式版本号,解码时提取对应的作者模式.
- 通过网络连接协商版本.
数据流--编码数据在存储与通信场景的应用
将编码好的数据从一个进程流向另一个进程,常见的方式如下,他们也有处理数据兼容的方式:
- 数据库:数据演化可以通过给数据库增加具有默认值的字段,比进行数据重写(迁移)更有效率.
-
REST
与RPC
: 取决于所采用的具体编码技术.在必要时维护多个版本的API
,REST
可以在URL
中使用版本号 - 异步消息传递:消息队列(不需要强制特定数据模型,通常只是包含元数据的字节序列)和
Actor
框架