数据格式
有很多种方式来组织回流数据,除了满足基本的序列化和反序列化功能、确保准确性外,可能还会有一些其他的需求。比如性能要求,成本要求(网络、存储),定制化回流等。基于这些需求,在不同的业务场景和技术氛围下,可能会有不同的选择。
非结构化数据
这种方式 Schema 或是固定的,或是利用类似于列式存储的方式有灵活的 Schema。
对于固定的 Schema,在、离线使用同一个列名列表,如果需要修改只能在后面追加字段;对于数据,使用特定的分隔符,通常使用 \001~\005 等不可见字符,减少数据冲突概率。这种方式对 Schema 的版本管理相对比较严格,需要手动序列化和反序列化,且存在数据存在分割符的可能,这种情况需要进行转义处理。
使用类似于列式存储方式的数据格式,比如 csv、parquet,数据文件本身存在 schema 信息,且回流后可以使用 spark 等工具直接读取,序列化和反序列化比较透明,且对应的库一般内置了转义操作。
非结构化的数据格式,都会存在一个问题,就是记录是单条的,比如对于一个用户需要回流多个物料,需要多次回流一级特征。当然也可以通过额外的工作,来避免。
结构化数据
除了非结构化的数据存储方式,还可以借助 IDL 定义结构化的数据格式。比如,使用 protobuf 来定义我们回流的数据结构。这种方式的好处是,可以定义非常复杂的数据结构,支持嵌套、多层级、分域等特性,且工具本身提供多种语言的序列化、反序列化能力,且无需关注转义的问题,同时节省 schema 和分隔符的存储占用。一次定义,多端使用。当然,这种方式也有它的问题,spark 不能直接读取,离线用的时候需要全部解包(哪怕只用部分字段)。
回流方式
这里的回流是指,从把封装到指定格式的数据,写入对象存储服务里面。
消息回流
使用消息中间件的方式回流是一种常用的方式。在线服务通过向消息中间件发送二进制格式的消息,消息中间件通过 Connector 或者专门的作业写入对象存储。
日志收集工具回流
常见的日志收集工具有 Fluentd、Vector 等,可以这是监听文件,按行/分隔符读取,也可以通过 socket 发送数据。收集工具一般可以设置 sink 位置,可以将日志写入消息中间件,也可直接写入对象存储。
日志文件回流
也可在日志文件滚动后,通过脚本或代码上传文件到对象存储。