《数据密集型应用系统设计》读书笔记整理(4)-- 数据编码与演化


一切都在改变,一刻都没有停止。
——Heraclitus,如柏拉图在Cratylus引用的那样(公元前360年)

数据编码格式

概述

当数据格式或模式发生变化时,需要对应用程序代码进行相应的调整:对于服务端,可能需要滚动升级(分阶段发布);对于客户端,一般情况下用户可能过一段不定的时间后才升级。即新旧版本的代码和新旧数据格式,可能会同时在系统内共存。

此时需要维持双向的兼容性:

  • 向后兼容:新代码可以读取旧代码编写的数据。
  • 向前兼容:旧代码可以读取新代码编写的数据,例如需要旧代码忽略新版本代码做的添加。

程序通常使用两种(至少)数据表示形式:

  1. 内存中,数据保存在对象、结构体、列表、数组、哈希表和树等结构中;这些数据结构对CPU的高效访问和操作进行了优化(通常使用指针)。
  2. 将数据写入文件或通过网络发送时,必须将其编码为某种自包含的字节序列,此时指针对其他进程是没有意义的。

因此,这两种表示之间需要进行类型的转化。从内存到字节序列转化称为编码(或序列化等),相反称为解码(或解析,反序列化)。

编码方案

许多编程语言内置有编码方案,但通常不是个好主意。一般倾向于使用可由不同编程语言编写和读取的标准化编码,例如JSON、XML和CSV,它们具有不错的可读性(文本格式),并且没有规定模式(所以在编码时需要包含所有的对象字段名称)。但它们也有缺陷:

  • 在XML和CSV中无法分辨数字,JSON不区分整数和浮点数,且不指定精度。
  • JSON和XML不支持二进制字符串。

Thrift和Protocol Buffer都需要模式来编码任意的数据,它们通过接口定义语言(IDL)来描述模式。它们有一些不错的属性:

  • 更紧凑,可省略编码数据中的字段名称。
  • 由于模式是解码所必须的,因此模式是一种有价值的文档形式

数据流模式

一些常见的进程间数据流动方式:通过数据库、通过服务调用、通过异步消息传递。

基于服务的数据流

将大型应用程序按照功能区域分解为较小的服务,这样当一个服务需要另一个服务的某些功能或数据时,就会向另一个服务发出请求。这种构建应用程序的方式传统上称为面向服务的体系结构(service-oriented architecture,SOA),最近则更名为微服务体系结构(microservices architecture)。微服务的一个关键设计目标是通过使服务可独立部署和演化,让应用程序更易于更改和维护。

当HTTP被用作服务通信的底层协议时,被称为web服务,使用在几种不同的上下文中:

  • 运行在用户设备上的客户端应用程序,通过HTTP向服务发出请求,通常通过公共互联网进行。
  • 一种服务向同一组织拥有的另一项服务提出请求,这些服务一般位于同个数据中心内。支持这种用例的软件有时被称为中间件。
  • 一种服务向不同组织所拥有的服务提出请求,经常需通过互联网。用于不同组织后端系统之间的数据交换。

有两种流行的web服务方法:REST和SOAP。

REST是一个基于HTTP原则的设计理念。使用URI标识资源,简单的数据格式,并使用HTTP进行缓存控制、身份验证和内容类型协商。
SOAP是一种基于XML的协议,用于发出网络API请求。SOAP web服务的API使用WSDL(web services description language,一种基于XML的语言)来描述。依赖工具支持、代码生成和IDE。

RPC模型试图使向远程网络服务发出请求看起来与在同一进程中调用编程语言中的函数或方法相同(这种抽象称为位置透明)。但使用远程服务和本地对象差别很大。而REST并不试图隐藏它要和网络交互的事实。REST是公共API的主流风格,而RPC框架主要侧重于同组织内多项服务之间的请求。

基于消息传递的数据流

与直接RPC相比,消息代理有几个优点:

  • 如果接收方不可用或过载,可以充当缓冲区,提高系统可靠性。
  • 可以将消息重新发送到崩溃的进程,防止消息丢失。
  • 避免发送发需要知道接收方的IP地址和端口。
  • 支持扇出,即将一条消息发送给多个接收方。
  • 在逻辑上将发送方和接收方分离。

参考文献:
[1] (美)Martin Kleppmann. 数据密集型应用系统设计(赵军平,吕云松,耿煜,李三平 译)[M]. 北京:中国电力出版社,2018.

Published

Author

Levin

Category

Web Arch

Tags

web arch database book report
Disqus loading now...