《数据密集型应用系统设计》 - 数据编码和演化(二)

简介: 《数据密集型应用系统设计》 - 数据编码和演化(二)

Avro

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第二十五天,点击查看活动详情同样是Apach的另一个二进制编码,Avro 是Hadoop的一个子项目,同样通过模式指定编码的一种数据结构,主要的进攻方向有两条:

  • Avro IDL 人工编译。

image.png

  • JSON 利于机器读取

image.png

这里再一次用到之前的案例,Avro 对于同样的内容仅仅使用32个字节的编码

image.png

这种二进制编码并没有显著的指示字段和数据类型,只是简单的连接列值而已,字符串仅仅为长度前缀,只有整数使用了可变长度编码。

这样的灵活度不是依靠数据结构本身支撑,而是换了一种思路,对于二进制数据的读写制定一套规则。

写模式和读模式

写模式:指的是对于任意数据可以使用已知模式的所有版本编码,比如编译到应用程序的模式。

读模式:需要根据模式解码某种数据的时候,期望数据符合某种模式。

和传统的编解码不一样,Avro 读写模式之间是可以进行相互转化的。

读写模式特点

最大的特点自在于读写模式不需要完全一致,只需要保持兼容即可,数据被解码读取的时候,通过对比查看读写模式同时将写模式转为读模式进行兼容,但是读写模式的转变需要符合Avro 的规范。

此外写模式和读模式的字段顺序不一样也是没有问题的,因为模式解析会通过字段名称对于字段进行匹配,如果读模式碰到了出现在写模式不在读模式的字段就会过滤,反过来如果读模式需要字段写模式没有提供会使用默认值转化。

模式演化规则

Avro的模式演化规则意味着把新版本的模式作为write,把旧版本的模式设置为reader,向后兼容则是新代码实现reader,旧版本模式为write。

这样实际上就是实现了新版本的写入会

Avro为了保持兼容性,只提供了默认值字段的增删权限,比如新增带有默认值的字段,使用新模式reader读取会使用默认值(如果读模式需要字段写模式没有提供会使用默认值转化),使用旧模式write则会直接过滤,并且只在新模式中可以看见新增默认值字段。

下面是模式演化的一个案例。

image.png

Avro 的前后兼容实质就是利write和reader这两个模式切换,利用新旧版本屏蔽的方式兼容代码。

Avro 除了这两个模式的特点之外,还有一个非常特殊的处理是 null 内容的处理,和多数编程语言不同,如果 Avro 中声明 允许为null值,必须要是联合类型。

联合类型:


union {null, long, string}

只有当null是一个联合的分支的时候才允许作为默认值,和ProtocolBuff 和Thrift 都不太一样,它没用默认标签或者列表维护的方式可选。

write 模式选择问题

Avro 还存在比较疑惑的问题那就是如何选择 reader模式如何选择write的版本,关键在于使用的上下文。

有很多记录的大文件:因为Hadoop中所有的记录都使用相同编码,所以在这种上下文中只需要开头包括write模式信息即可表示。

具有单独写入记录的数据库:不同的记录需要不同的模式和不同的版本处理,处理这种情况最简单的方式是每一个记录编码的开头记录一个版本号,并且在数据库中保留一个模式版本列表。reader模式通过从记录的“数据库”中提取write模式完成对应的操作,例如Espresso231就是这样工作的。

网络连接发送记录:在建立连接的时候建立模式建立版本,然后在生命周期当中完成工作,Avro RPC的工作原理就是如此的。

动态生成模式

动态生成模式是 Avro 的还有一项特点是对于动态生成的模式兼容更好,因为不带任何的标点符号,可以快速完成不同模式之间的转化。

比如,如果数据库模式转为 Avro 模式,只需要根据关系模式作为中转即可快速完成转化,同时根据write和read模式的转变快速完成被改变字段的同步工作。

这意味着 Avro的模式转化似乎是他原生的内容。如果使用 Thrift 或者 Protocol Buffers,则需要额外维护一套映射规则,同时维护模式生成器要特别小心错误分配标签的问题。

动态生成模式是 Avro 的设计目标之一,所以它在这一块表现十分出色。

代码生成和动态类型语言

需要注意的是这样的编码框架比较常用于静态语言,对于动态类型编程语言实际上并没有太多的意义。此外对于Avro这样动态生成模式的框架代码生成反而是一种累赘,因为本身就可以通过动态模式完成模式转化。

最后Avro的动态生成模式经常和动态类型数据处理语言结合使用。

模式的优点

通过上面的一系列对比讨论,我们发现模式对比JSON和XML格式相比,使用独特的框架设计以及更简单易懂可维护的特点,被广泛的编程语言支持。

实际上模式框架本身的思想并不是什么新东西,ASN.l 在 1984年首次被标准化的模式定义语言中可以看到类似的影子,ASN.I 本身也被用于SSL证书的二进制编码(DER)当中。

对比模式和XML以及JSON,它们通常具备下面的特点:

  • 数据更加紧凑,甚至可以省略数据当中的字段名。
  • 模式本身具备文档化价值 ,可维护性要强于XML和JSON。
  • 模式具备前后兼容性的检查,对于大系统的升级维护这是非常有必要的。
  • 对于静态类型编程语言的用户来说,从模式生成代码的能力是有用的,它能够在编译时进行类型检查。


相关文章
|
6月前
|
存储 NoSQL Redis
单线程模型想象不到的高并发能力、多路复用是效率杠杆
单线程模型想象不到的高并发能力、多路复用是效率杠杆
|
分布式计算 NoSQL Java
局部性原理——各类优化的基石(2)
CDN的全称是Content Delivery Network,即内容分发网络(图片来自百度百科) 。CDN常用于大的素材下发,比如图片和视频,你在淘宝上打开一个图片,这个图片其实会就近从CDN机房拉去数据,而不是到阿里的机房拉数据,可以减少阿里机房的出口带宽占用,也可以减少用户加载素材的等待时间。
86 0
|
6月前
|
存储 并行计算 算法
【深度挖掘Java性能调优】「底层技术原理体系」深入挖掘和分析如何提升服务的性能以及执行效率(性能三大定律)
【深度挖掘Java性能调优】「底层技术原理体系」深入挖掘和分析如何提升服务的性能以及执行效率(性能三大定律)
86 0
|
4月前
业务系统架构实践问题之平衡SPI的语义精确性和实现的复杂性问题如何解决
业务系统架构实践问题之平衡SPI的语义精确性和实现的复杂性问题如何解决
|
6月前
|
存储 SQL NoSQL
应用性能设计的圣杯:读写扩散的概念与实践
本文结合这三年作者在钉钉见到的应用架构,以及一些业界的实践分享,整理出一篇关于应用读写扩散设计的维基。
|
6月前
|
XML JSON JavaScript
《数据密集型应用系统设计》 - 数据编码和演化(一)
《数据密集型应用系统设计》 - 数据编码和演化(一)
66 0
《数据密集型应用系统设计》 - 数据编码和演化(一)
|
6月前
|
消息中间件 API 数据库
《数据密集型应用系统设计》 - 数据编码和演化(三)
《数据密集型应用系统设计》 - 数据编码和演化(三)
61 0
《数据密集型应用系统设计》 - 数据编码和演化(三)
|
缓存 NoSQL 应用服务中间件
零拷贝并非万能解决方案:重新定义数据传输的效率极限
本文讨论了零拷贝在优化数据传输效率方面的局限性。尽管零拷贝技术在减少数据传输过程中的内存拷贝次数方面有很大的优势,但它并非适用于所有情况。文章介绍了一些其他的优化方法,如异步I/O和直接I/O的组合、根据文件大小选择不同的优化方式。至此,我们的计算机基础专栏就结束了,不知道大家有没有发现,操作系统底层提供了丰富的解决方案来支持应用程序的复杂性和可扩展性。对于任何工作中遇到的问题,我们都可以从操作系统的角度寻找解决方法。
139 0
零拷贝并非万能解决方案:重新定义数据传输的效率极限
|
存储 缓存 NoSQL
局部性原理——各类优化的基石(1)
学过计算机底层原理、了解过很多架构设计或者是做过优化的同学,应该很熟悉局部性原理。即便是非计算机行业的人,在做各种调优、提效时也不得不考虑到局部性,只不过他们不常用局部性一词。如果抽象程度再高一些,甚至可以说地球、生命、万事万物都是局部性的产物,因为这些都是宇宙中熵分布布局、局部的熵低导致的,如果宇宙中处处熵一致,有的只有一篇混沌。
115 0
|
移动开发 5G
带你读《5G大规模天线增强技术》——1.3.1 数学基础
带你读《5G大规模天线增强技术》——1.3.1 数学基础