分享

Apache Avro序列化

 关平藏书 2018-09-04

Apache Avro是一种与编程语言无关的序列化格式。Doug Cutting创建了这个项目,目的是提供一种共享数据文件的方式。
Avro数据通过与语言无关的schema来定义。schema 通过JSON来描述,数据被序列化成二进制文件或JSON文件,不过一般会使用二进制文件。Avro 在读写文件时需要用到schema,schema一般会被内嵌在数据文件里。
Avro有一个很有意思的特性是,当负责写消息的应用程序使用了新的schema,负责读消息的应用程序可以继续处理消息而无需做任何改动,这个特性使得它特别适合用在像Kafka这样的消息系统上。假设最初的schema是这样的:

  • {"namespace": "customerManagenent.avro""type": "record" ,
  • "name": "Customer","fields": [
  • {"name": "id", "type": "int"},
  • {"name": "name", "type": "string"},
  • {"name": "faxNumber", "type": ["null", "string"], "default": "null"}
  • ]
  • }

id和name字段是必需的,faxNunber 是可选的,默认为null。
假设我们已经使用了这个schema几个月的时间,并用它生成了几个太字节的数据。现在,我们决定在新版本里做一些修改。 因为在21世纪不再需要faxNumber字段,需要用email字段来代替它。新的schema如下:

  • {"nanespace": "customerManagement . avro" ,"type": "record" ,
  • "name": "Customer","fields": [
  • {"name": "id", "type": "int"},
  • {"name": "nane", "type": "string"},
  • {"name": "email", "type": ["null", "string"], "default": "null"}
  • ]
  • }

更新到新版的schema后,旧记录仍然包含faxNumber 字段,而新记录则包含email字段。部分负责读取数据的应用程序进行了升级,那么它们是如何处理这些变化的呢?

在应用程序升级之前,它们会调用类似getName()、getId() 和getFaxNunber()这样的方法。如果碰到使用新schema构建的消息,getName() 和getId()方法仍然能够正常返回,但getFaxNumber()方法会返回null,因为消息里不包含传真号码。
在应用程序升级之后,getEmail()方法取代了getFaxNumber() 方法。如果碰到一个使用旧schema构建的消息,那么getEmail()方法会返回null,因为旧消息不包含邮件地址。
现在可以看出使用Avro的好处了:我们修改了消息的schema,但并没有更新所有负责读取数据的应用程序,而这样仍然不会出现异常或阻断性错误,也不需要对现有数据进行大幅更新。

Avro的数据文件里包含了整个schema,不过这样的开销是可接受的。但是如果在每条Kafka记录里都嵌入schema,会让记录的大小成倍地增加。不过不管怎样,在读取记录时仍然需要用到整个schema,所以要先找到schema。我们遵循通用的结构模式并使用"schema注册表"来达到目的。schema注册表并不属于Kafka,现在已经有一些开源的schema注册表实现。在这个例子里,我们使用的是Conluent Schema Registry。 该注册表的代码可以在GitHub上找到,你也可以把它作为Confuent平台的一部分进行安装。如果你决定使用这个注册表,可以参考它的文档。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多