摘要¶
序列化和反序列化是系统选型或重构一个重要的环节,在分布式、大数据量系统设计里面更为显著。恰当的序列化协议不仅可以提高系统的通用性、强健性、安全性、优化系统性能,而且会让系统更加易于调试、便于扩展。本文借助网络中存在众多材料从多个角度分析和讲解“序列化与反序列化”,并对比当前流行的几种序列化协议。
当服务本身需要处理Terabyte到Gigabyte级别的数据时,为了提供高质量的数据服务,为了实现与上下游各系统进行良好的对接,序列化与反序列化的选型往往是系统设计的一个重要考虑因素。
本文的内容组织方式如下:
- 第一部分给出了序列化和反序列化的定义,以及其在通讯协议中所处的位置。
- 第二部分从使用者的角度探讨了序列化协议的一些特性。
- 第三部分描述在具体的实施过程中典型的序列化组件,并与数据库组建进行了类比。
- 第四部分分别讲解了目前常见的几种序列化协议的特性,应用场景,并对相关组件进行举例。
- 最后一部分,基于各种协议的特性,以及相关benchmark数据,给出了作者的技术选型建议。
定义¶
互联网的产生带来了机器间通讯的需求,而互联通讯的双方需要采用约定的协议,序列化和反序列化属于通讯协议的一部分。通讯协议往往采用分层模型,不同模型每层的功能定义以及颗粒度不同,例如:TCP/IP协议是一个四层协议,而OSI模型却是七层协议模型。在OSI七层协议模型中展现层(Presentation Layer)的主要功能是把应用层的对象转换成一段连续的二进制串,或者反过来,把二进制串转换成应用层的对象–这两个功能就是序列化和反序列化。一般而言,TCP/IP协议的应用层对应与OSI七层协议模型的应用层,展示层和会话层,所以序列化协议属于TCP/IP协议应用层的一部分。本文对序列化协议的讲解主要基于OSI七层协议模型。
- 序列化: 将数据结构或对象转换成二进制串的过程
- 反序列化:将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程
序列化的影响因素¶
- 序列化后的数据最好是易于人类阅读的
- 实现的复杂度是否足够低
- 序列化和反序列化的速度越快越好
- 序列化后的信息密度越大越好,也就是说,同样的一个结构化数据,序列化之后占用的存储空间越小越好
数据结构、对象与二进制串¶
不同的计算机语言中,数据结构,对象以及二进制串的表示方式并不相同。
数据结构和对象:对于类似Java这种完全面向对象的语言,工程师所操作的一切都是对象(Object),来自于类的实例化。在Java语言中最接近数据结构的概念,就是POJO(Plain Old Java Object)或者Javabean--那些只有setter/getter方法的类。而在C++这种半面向对象的语言中,数据结构和struct对应,对象和class对应。
二进制串:序列化所生成的二进制串指的是存储在内存中的一块数据。C++
语言具有内存操作符,所以二进制串的概念容易理解,例如,C++
语言的字符串可以直接被传输层使用,因为其本质上就是以’\0’结尾的存储在内存中的二进制串。在Java语言里面,二进制串的概念容易和String混淆。实际上String 是Java的一等公民,是一种特殊对象(Object)。对于跨语言间的通讯,序列化后的数据当然不能是某种语言的特殊数据类型。二进制串在Java里面所指的是byte[],byte是Java的8中原生数据类型之一(Primitive data types)。
序列化协议特性¶
每种序列化协议都有优点和缺点,它们在设计之初有自己独特的应用场景。在系统设计的过程中,需要考虑序列化需求的方方面面,综合对比各种序列化协议的特性,最终给出一个折衷的方案。
通用性¶
参考文献¶
- 美团技术团队,序列化和反序列化,2015