网易游戏资深开发工程师林小铂为大家带来网易游戏基于 Flink 的流式 ETL 建设的介绍。内容包括:
- 业务背景
- 专用 ETL
- EntryX 通用 ETL
- 调优实践
- 未来规划
一. 业务背景
网易游戏 ETL 服务概况
网易游戏的基础数据主要日志方式采集,这些日志通常是非结构化或半结构化数据,需要经过数据集成 ETL 才可以入库至实时或离线的数据仓库。此后,业务用户才可以方便地用 SQL 完成大部分数据计算,包括实时的 Flink SQL 和离线的 Hive 或 Spark。
网易游戏数据集成的数据流与大多数公司大同小异,主要有游戏客户端日志、游戏服务端日志和其他周边基础的日志,比如 Nginx access log、数据库日志等等。这些日志会被采集到统一的 Kafka 数据管道,然后经由 ETL 入库服务写入到 Hive 离线数据仓库或者 Kafka 实时数据仓库。
这是很常见的架构,但在我们在需求方面是有一些比较特殊的情况。
网易游戏流式 ETL 需求特点
首先,不同于互联网、金融等行业基本常用 MySQL、Postgres 等的关系型数据库,游戏行业常常使用 MongoDB 这类 schema-free 的文档型数据库。这给我们 ETL 服务带来的问题是并没有一个线上业务的准确的 schema 可以依赖,在实际数据处理中,多字段或少字段,甚至一个字段因为玩法迭代变更为完全不同的格式,这样的情况都是可能发生的。这样的数据异构问题给我们 ETL 的数据清洗带来了比较高的成本。
其次,也是由于数据库选型的原因,大部分业务的数据库模式都遵循了反范式设计,会刻意以复杂内嵌的字段来避免表间的 join。这种情况给我们带来的一个好处是,在数据集成阶段我们不需要去实时地去 join 多个数据流,坏处则是数据结构可能会非常复杂,多层嵌套十分常见。
然后,由于近年来实时数仓的流行,我们也同样在逐步建设实时数据仓库,所以复用现有的 ETL 管道,提取转换一次,加载到实时离线两个数据仓库,成为一个很自然的发展方向。
最后,我们的日志类型多且变更频繁,比如一个玩法复杂的游戏,可能有 1,000 个以上的日志类型,每两周可能就会有一次发版。在这样的背景下 ETL 出现异常数据是不可避免的。因此我们需要提供完善的异常处理,让业务可以及时得知数据异常和通过流程修复数据。
日志分类及特点
为了更好地针对不同业务使用模式优化,我们对不同日志类型的业务提供了不同的服务。我们的日志通常分为三个类型:运营日志、业务日志和程序日志。
运营日志记录的是玩家行为事件,比如登录帐号、领取礼包等。这类日志是最为重要日志,有固定的格式,也就是特定 header + json 的文本格式。数据的主要用途是做数据报表、数据分析还有游戏内的推荐,比如玩家的组队匹配推荐。
业务日志记录的是玩家行为以外的业务事件,这个就比较广泛,比如 Nginx access log、CDN 下载日志等等,这些完全没有固定格式,可能是二进制也可能是文本。主要用途类似于运营日志,但更加丰富和定制化。
程序日志记录是程序的运行情况,也就是平时我们通过日志框架打的 INFO、ERROR 这类日志。程序日志主要用途是检索定位运行问题,通常是写入 ES,但有时数量过大或者需要提取指标分析时,也会写入数据仓库。
网易游戏 ETL 服务剖析
针对这些日志分类,我们具体提供了三类 ETL 入库的服务。首先是运营日志专用的 ETL,这会根据运营日志的模式进行定制化。然后是通用的面向文本日志的 EntryX ETL 服务,它会服务于运营日志以外的所有日志。最后是 EntryX 无法支持的特殊 ETL 需求,比如有加密或者需要进行特殊转换的数据,这种情况下我们就会针对性地开发 ad-hoc 作业来处理。
二. 运营日志专用 ETL
运营日志 ETL 发展历程
运营日志 ETL 服务有着一个比较久的历史。大概在 2013 年,网易游戏就建立了基于 Hadoop Streaming + Python 预处理/后处理的