从批处理 ETL 到流式处理:一个来自 Netflix 的案例

阅读数:2634 2018 年 3 月 12 日

要点

  • 在将基于批处理的 ETL 迁移到流式处理的过程中,需要考虑很多因素,并做出很多权衡。不能只是因为流式处理技术的流行而将所有东西都使用流来处理。
  • 这篇文章的案例来自 Netflix,他们使用 Apache Flink 代替原有的批处理系统。之所以选择 Flink,是因为他们需要实时的事件处理和可扩展的自定义窗口。
  • 在迁移过程中碰到了很多困难,例如,如何从实时数据源获取数据、如何管理元数据、如何进行数据恢复、如何处理乱序数据,以及如何做好运维工作。
  • 流式处理为业务带来了好处,例如,可以使用最新的数据来训练机器学习算法。
  • 流式处理也带来了技术方面的好处,例如,可以更灵活地节省存储成本、与其他实时系统集成。

在 2017 年的纽约 QCon大会上,Shriya Arora 呈现了“Personalizing Netflix with Streaming Datasets”的演讲,分享了 Netflix 的一个数据作业迁移案例,他们使用 Flink 替代了原先基于批处理的 ETL。

Arora是 Netflix 的一名高级数据工程师,在演讲刚开始,Arora 说明了演讲的主要目的是帮助听众们了解流式处理数据管道是否能够帮助他们解决传统 ETL 批处理作业存在的问题。除此之外,她还探讨了在向流式处理迁移过程中需要注意的问题和需要作出的权衡。Arora 表示,“批处理并没有死去”,尽管现在有很多流式处理引擎,但没有哪一个能够单独提供最佳的解决方案。

Netflix 的核心使命是让用户能够在任意时刻、任意地点观看定制化的视频内容。Netflix 每天需要处理来自 190 多个国家 1 个多亿个活跃用户所生成的 4500 亿个事件,这些用户每天观看视频的总时间超过 1 亿 2500 万个小时。Netflix 的系统采用了微服务架构,服务之间通过远程过程调用(RPC)和消息进行通信。生产环境的 Kafka 集群拥有 700 多个主题,负责管理消息,同时向数据处理管道输送数据。

Netflix 的数据工程分析(Data Engineering and Analytics,DEA)团队和 Netflix Research 团队负责运营定制化系统。微服务应用程序生成用户和系统数据,这些数据被收集到Netflix Keystone数据管道中,Keystone 是一个 PB 级别的实时数据流式处理系统。传统的批处理是这样的:先将这些数据保存到部署在亚马逊 S3 上的 Hadoop Distributed File System(HDFS)中,然后使用 Apache Spark、Pig、Hive 或 Hadoop 来处理数据。处理过的数据被保存到数据库表或 Elasticsearch 中,Research 团队、下游的系统或仪表盘应用程序就可以使用这些数据。与此同时,他们也使用 Apache Kafka 将数据导向 Flink 或 Spark Streaming。

在介绍他们如何将 ETL 批处理作业转成流式处理之前,Arora 告诫听众,“不要尝试流式化所有的东西”。流式处理确实能够带来业务上的好处,比如可以使用最新的数据来训练机器学习算法、为市场创新提供新的想法,以及增加开发新机器学习算法的可能性。流式处理也能带来技术上的好处,比如更灵活地节约存储成本(原始数据不需要以最初的形式保存)、更快的回退(批处理在发生故障时需要很长的回退时间)、实时的审计,以及与其他实时系统集成。

在实现流式处理时,最大的挑战是如何选择一个合适的引擎。首先要搞清楚的是,数据的处理是基于事件流的还是基于微批次的。在 Arora 看来,微批次只是批处理的一个子集,只不过是将时间窗口从一天变成了一个小时或一分钟,数据的处理仍然是基于一大段数据,而不是基于事件。如果说只是期望更快一点获得结果,而且企业已经在批处理上做了大量投入,那么迁移到微批次处理可能是最合适的低成本解决方案。

在选择引擎时,另一个需要考虑的问题是:哪些特性是最为关键的。这个问题不是通过一场头脑风暴就能解决的,通常只有在对问题有深入了解并经过深度调研之后才能得出答案。Netflix 的系统需要“会话化”的事件数据,也就是基于会话的时间窗口。各种引擎对该特性的支持程度各不一样,最后,他们选择了 Flink,因为相比 Spark Streaming,Flink 提供了更好的自定义窗口支持(不过,在这次演讲之后,Spark 发布了 2.2.0,以及最近发布的 2.3.0,提供了Structured Streaming和高级的会话处理能力)。

还一个需要考虑的问题是:是否需要支持lambda 架构。这里所说的 lambda 不是指 AWS Lambda 或无服务器架构。在数据处理领域,lambda 架构指的是同时使用批处理和流式处理的方式来处理海量数据,以便在延迟、吞吐量和容错方面做出权衡。批处理层提供了整体精确的批次数据视图,同时实现了一个速度层,用于实时的流式处理,提供几近完整的实时在线数据视图。如果已经存在一个批处理作业,只需要再加入一个速度层,那么,可以选择一个 lambda 架构的引擎,这样就可以重用已有的代码。

在选择流式处理引擎时还需要考虑如下的问题:

  • 公司的其他团队在使用什么引擎?如果说采用新技术需要大量投入,那么或许可以考虑利用公司已有的技术。
  • 公司现有的 ETL 系统是怎样的?新技术是否能够与已有的数据源和数据池很好地接在一起?
  • 新技术的学习曲线是怎样的?批处理所采用的是什么引擎和编程语言?

演讲的倒数第二部分主要介绍了 Netflix 是如何将批处理 ETL 转成流式 ETL 的。之前,Netflix 的 DEA 团队使用批处理 ETL 来分析播放源(Source of Play)和发现源(Source of Discovery),至少需要 8 个小时才能完成。播放源是指从 Netflix 应用程序的主页面到用户开始播放视频的位置,而发现源是指用户在主页面上发现想观看内容的位置。DEA 团队的终极目标是优化主页面,最大化用户观看的转化率,并减小从事件发生到得出分析结果之间的延迟(当时是超过了 24 小时),而实时处理可以大幅缩短这一差距。

经过对“发现源”问题的深入分析,Netflix 发现,流式处理引擎可以帮助他们实现如下的一些目标:处理高吞吐量数据(全球用户每天生成大概 1 亿个播放事件);通过胖客户端(基于 RPC)与直播微服务发生交互,以便对播放事件进行填充;与 Netflix 生态系统的其他系统进行集成;集中式的日志和告警;支持低变更频率的输入数据(比如包含电影元数据或国家人口统计资料的元数据表)。

最后,Arora 和她的团队选择了 Flink,以及其他相关技术:

  • 使用 Kafka 作为消息总线;
  • 使用 Hive 进行数据摘要、查询和分析,Hive 提供了 SQL 风格的接口(这里主要用在元数据上);
  • 使用亚马逊 S3 存储数据(HDFS);
  • 通过Netflix OSS与 Netflix 生态系统的其他部分集成;
  • 使用 Apache Mesos 调度和执行作业;
  • 使用Spinnaker实现持续交付。

下图展示了发现源的整体管道架构:

Arora 总结了 DEA 团队在迁移过程中面临的主要挑战:

  • 从直播源获取数据:
    • 迁移后的作业需要访问完整的用户播放历史。
    • 理论上,可以很容易地通过流式处理来实现,因为与 Netflix 生态系统的集成和数据处理的实时性意味着处理一个事件只需要一个简单的 RPC 调用。
    • 不过,因为 Flink 和 Netflix OSS 都是使用 Java 开发,有时候会出现类库的兼容性问题(也就是所谓的“JAR 包地狱”)。
  • 侧面输入:
    • 流式处理作业中的每一项元数据可能在获取直播源数据时就已经获取过了。
    • 重复获取数据需要更多的网络开销,最终会导致不合理的资源利用。
    • 所以,他们将元数据缓存在内存里,每 15 分钟刷新一次。
  • 数据恢复:
    • 如果一个批处理作业因为基础设施问题而运行失败,可以重新运行,因为数据仍然保存在底层的对象存储中,比如 HDFS。但在流式处理中可能不是这么一回事,因为原始事件被处理之后可能就不存在了。
    • 在 Netflix 生态系统中,消息总线(Kafka)的 TTL 可能是 4 到 6 个小时,如果一个流式处理作业执行失败,并且无法在 TTL 期限内检测出来并加以修复,那么数据就会丢失掉。
    • 解决办法是将原始数据保存在 HDFS 里(保留一到两天),便于后续重新处理。
  • 乱序事件:
    • 如果数据管道出现故障,需要进行数据恢复,这意味着“旧”数据将会混杂在新的实时数据中。
    • 问题在于如何正确地使用数据的生成时间来标记迟到的数据。
    • DEA 团队选择自己实现时间窗口,并进行后处理(Post Processing),确保使用的是正确的事件时间。
  • 监控和告警的增长:
    • 一旦发生管道故障,相应的团队必须立即收到告警。
    • 如果不能及时触发告警,将会造成数据丢失。
    • 实现高效的监控、日志和告警至关重要。

Arora 在演讲的最后表示,尽管将批处理 ETL 迁移到流式处理能够在业务和技术两个方面带来很多好处,但同时也带来了很多挑战。采用流式处理的工程师们需要为此付出代价,因为大部分传统的 ETL 都是基于批处理的,而基于流式处理进行机器学习训练还只是个相对新兴的领域。数据团队也需要处理运维问题,比如参与轮班待命或处理中断事故。可以说,批次故障需要得到紧急处理,而流式故障需要立即得到解决。企业需要投入资源构建具有弹性的基础设施,构建高效的监控和告警机制,并创建能够支持快速迭代和部署的持续交付管道。

Arora 在 2017 年纽约 QCon 大会的演讲视频可以在 InfoQ 网站上找到。

关于作者

Daniel Bryant 是组织和技术的变革者。他目前的工作包括:通过引入更好的需求和计划模型在企业中促进敏捷的实施、专注于与敏捷开发相关的架构问题、促进持续集成和持续交付的实施。他目前的技术领域主要包括 DevOps 工具、云计算 / 容器平台和微服务实现。他是伦敦 Java 社区(LJC)的负责人,是多个开源项目的贡献者,为多个知名网站(InfoQ、DZone 和 Voxxed)撰文,并定期在国际大会(QCon、JavaOne 和 Devoxx)上演讲。

查看英文原文Migrating Batch ETL to Stream Processing: A Netflix Case Study with Kafka and Flink

收藏

评论

微博

发表评论

注册/登录 InfoQ 发表评论