小米流式平台架构演进与实践

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
简介: 小米业务线众多,从信息流,电商,广告到金融等覆盖了众多领域,小米流式平台为小米集团各业务提供一体化的流式数据解决方案,主要包括数据采集,数据集成和流式计算三个模块。目前每天数据量达到 1.2 万亿条,实时同步任务 1.5 万,实时计算的数据 1 万亿条。

作者:夏军@小米

小米业务线众多,从信息流,电商,广告到金融等覆盖了众多领域,小米流式平台为小米集团各业务提供一体化的流式数据解决方案,主要包括数据采集,数据集成和流式计算三个模块。目前每天数据量达到 1.2 万亿条,实时同步任务 1.5 万,实时计算的数据 1 万亿条。

伴随着小米业务的发展,流式平台也经历三次大升级改造,满足了众多业务的各种需求。最新的一次迭代基于 Apache Flink,对于流式平台内部模块进行了彻底的重构,同时小米各业务也在由 Spark Streaming 逐步切换到 Flink。

背景介绍

小米流式平台的愿景是为小米所有的业务线提供流式数据的一体化、平台化解决方案。具体来讲包括以下三个方面:

  • 流式数据存储:流式数据存储指的是消息队列,小米开发了一套自己的消息队列,其类似于 Apache kafka,但它有自己的特点,小米流式平台提供消息队列的存储功能;
  • 流式数据接入和转储:有了消息队列来做流式数据的缓存区之后,继而需要提供流式数据接入和转储的功能;
  • 流式数据处理:指的是平台基于 Flink、Spark Streaming 和 Storm 等计算引擎对流式数据进行处理的过程。

1.jpg

下图展示了流式平台的整体架构。从左到右第一列橙色部分是数据源,包含两部分,即 User 和 Database。

  • User 指的是用户各种各样的埋点数据,如用户 APP 和 WebServer 的日志,其次是 Database 数据,如 MySQL、HBase 和其他的 RDS 数据。
  • 中间蓝色部分是流式平台的具体内容,其中 Talos 是小米实现的消息队列,其上层包含 Consumer SDK 和 Producer SDK。
  • 此外小米还实现了一套完整的 Talos Source,主要用于收集刚才提到的用户和数据库的全场景的数据。

Talos Sink 和 Source 共同组合成一个数据流服务,主要负责将 Talos 的数据以极低的延迟转储到其他系统中;Sink 是一套标准化的服务,但其不够定制化,后续会基于 Flink SQL 重构 Talos Sink 模块。

2.jpg

下图展示了小米的业务规模。在存储层面小米每天大概有 1.2 万亿条消息,峰值流量可以达到 4300 万条每秒。转储模块仅 Talos Sink 每天转储的数据量就高达 1.6 PB,转储作业目前将近有 1.5 万个。每天的流式计算作业超过 800 个,Flink 作业超过 200 个,Flink 每天处理的消息量可以达到 7000 亿条,数据量在 1 PB 以上。

3.jpg

小米流式平台发展历史

小米流式平台发展历史分为如下三个阶段:

  • Streaming Platform 1.0:小米流式平台的 1.0 版本构建于 2010 年,其最初使用的是 Scribe、Kafka 和 Storm,其中 Scribe 是一套解决数据收集和数据转储的服务。
  • Streaming Platform 2.0:由于 1.0 版本存在的种种问题,我们自研了小米自己的消息队列 Talos,还包括 Talos Source、Talos Sink,并接入了 Spark Streaming。
  • Streaming Platform 3.0:该版本在上一个版本的基础上增加了 Schema 的支持,还引入了 Flink 和 Stream SQL。

4.jpg

Streaming Platform 1.0 整体是一个级联的服务,前面包括 Scribe Agent 和 Scribe Server 的多级级联,主要用于收集数据,然后满足离线计算和实时计算的场景。离线计算使用的是 HDFS 和 Hive,实时计算使用的是 Kafka 和 Storm。虽然这种离线加实时的方式可以基本满足小米当时的业务需求,但也存在一系列的问题。

  • 首先是 Scribe Agent 过多,而配置和包管理机制缺乏,导致维护成本非常高;
  • Scribe 采用的 Push 架构,异常情况下无法有效缓存数据,同时 HDFS / Kafka 数据相互影响;
  • 最后数据链级联比较长的时候,整个全链路数据黑盒,缺乏监控和数据检验机制。

5.jpg

为了解决 Streaming Platform 1.0 的问题,小米推出了 Streaming Platform 2.0 版本。该版本引入了 Talos,将其作为数据缓存区来进行流式数据的存储,左侧是多种多样的数据源,右侧是多种多样的 Sink,即将原本的级联架构转换成星型架构,优点是方便地扩展。

  • 由于 Agent 自身数量及管理的流较多(具体数据均在万级别),为此该版本实现了一套配置管理和包管理系统,可以支持 Agent 一次配置之后的自动更新和重启等。
  • 此外,小米还实现了去中心化的配置服务,配置文件设定好后可以自动地分发到分布式结点上去。
  • 最后,该版本还实现了数据的端到端监控,通过埋点来监控数据在整个链路上的数据丢失情况和数据传输延迟情况等。

6.jpg

Streaming Platform 2.0 的优势主要有:

  • 引入了 Multi Source & Multi Sink,之前两个系统之间导数据需要直接连接,现在的架构将系统集成复杂度由原来的 O(M*N) 降低为 O(M+N);
  • 引入配置管理和包管理机制,彻底解决系统升级、修改和上线等一系列问题,降低运维的压力;
  • 引入端到端数据监控机制,实现全链路数据监控,量化全链路数据质量;
  • 产品化解决方案,避免重复建设,解决业务运维问题。

7.jpg

下图详细介绍一下 MySQL 同步的案例,场景是将 MySQL 的一个表通过上述的机制同步到消息队列 Talos。具体流程是 Binlog 服务伪装成 MySQL 的 Slave,向 MySQL 发送 Dump binlog 请求;MySQL 收到 Dump 请求后,开始推动 Binlog 给 Binlog 服务;Binlog 服务将 binlog 以严格有序的形式转储到 Talos。之后会接入 Spark Streaming 作业,对 binlog 进行解析,解析结果写入到 Kudu 表中。目前平台支持写入到 Kudu 中的表的数量级超过 3000 个。

8.jpg

Agent Source 的功能模块如下图所示。其支持 RPC、Http 协议,并可以通过 File 来监听本地文件,实现内存和文件双缓存,保证数据的高可靠。平台基于 RPC 协议实现了 Logger Appender 和 RPC 协议的 SDK;对于 Http 协议实现了 HttpClient;对于文件实现了 File Watcher 来对本地文件进行自动地发现和扫描,Offset Manager 自动记录 offset;Agent 机制与 K8S 环境深度整合,可以很容易地和后端的流式计算等相结合。

9.jpg

下图是 Talos Sink 的逻辑流程图,其基于 Spark Streaming 来实现一系列流程。最左侧是一系列 Talos Topic 的 Partition 分片,基于每个 batch 抽象公共逻辑,如 startProcessBatch() 和 stopProcessBatch(),不同 Sink 只需要实现 Write 逻辑;不同的 Sink 独立为不同的作业,避免相互影响;Sink 在 Spark Streaming 基础上进行了优化,实现了根据 Topic 流量进行动态资源调度,保证系统延迟的前提下最大限度节省资源。

10.jpg

下图是平台实现的端到端数据监控机制。具体实现是为每个消息都有一个时间戳 EventTime,表示这个消息真正生成的时间,根据 EventTime 来划分时间窗口,窗口大小为一分钟,数据传输的每一跳统计当前时间窗口内接受到的消息数量,最后统计出消息的完整度。延迟是计算某一跳 ProcessTime 和 EventTime 之间的差值。

12.jpg

Streaming Platform 2.0 目前的问题主要有三点:

  • Talos 数据缺乏 Schema 管理,Talos 对于传入的数据是不理解的,这种情况下无法使用 SQL 来消费 Talos 的数据;
  • Talos Sink 模块不支持定制化需求,例如从 Talos 将数据传输到 Kudu 中,Talos 中有十个字段,但 Kudu 中只需要 5 个字段,该功能目前无法很好地支持;
  • Spark Streaming 自身问题,不支持 Event Time,端到端 Exactly Once 语义。

13.jpg

基于 Flink 的实时数仓

为了解决 Streaming Platform 2.0 的上述问题,小米进行了大量调研,也和阿里的实时计算团队做了一系列沟通和交流,最终决定将使用 Flink 来改造平台当前的流程,下面具体介绍小米流式计算平台基于Flink的实践。

使用 Flink 对平台进行改造的设计理念如下:

  • 全链路 Schema 支持,这里的全链路不仅包含 Talos 到 Flink 的阶段,而是从最开始的数据收集阶段一直到后端的计算处理。需要实现数据校验机制,避免数据污染;字段变更和兼容性检查机制,在大数据场景下,Schema 变更频繁,兼容性检查很有必要,借鉴 Kafka 的经验,在 Schema 引入向前、向后或全兼容检查机制。
  • 借助 Flink 社区的力量全面推进 Flink 在小米的落地,一方面 Streaming 实时计算的作业逐渐从 Spark、Storm 迁移到 Flink,保证原本的延迟和资源节省,目前小米已经运行了超过 200 个 Flink 作业;另一方面期望用 Flink 改造 Sink 的流程,提升运行效率的同时,支持 ETL,在此基础上大力推进 Streaming SQL;
  • 实现 Streaming 产品化,引入 Streaming Job 和 Streaming SQL 的平台化管理;
  • 基于 Flink SQL 改造 Talos Sink,支持业务逻辑定制化

14.jpg

下图是 Streaming Platform 3.0 版本的架构图,与 2.0 版本的架构设计类似,只是表达的角度不同。具体包含以下几个模块:

  • 抽象 Table:该版本中各种存储系统如 MySQL 和 Hive 等都会抽象成 Table,为 SQL 化做准备。
  • Job 管理:提供 Streaming 作业的管理支持,包括多版本支持、配置与Jar分离、编译部署和作业状态管理等常见的功能。
  • SQL 管理:SQL 最终要转换为一个 Data Stream 作业,该部分功能主要有 Web IDE 支持、Schema 探查、UDF/维表 Join、SQL 编译、自动构建 DDL 和 SQL 存储等。
  • Talos Sink:该模块基于 SQL 管理对 2.0 版本的 Sink 重构,包含的功能主要有一键建表、Sink 格式自动更新、字段映射、作业合并、简单 SQL 和配置管理等。前面提到的场景中,基于 Spark Streaming 将 Message 从 Talos 读取出来,并原封不动地转到 HDFS 中做离线数仓的分析,此时可以直接用 SQL 表达很方便地实现。未来希望实现该模块与小米内部的其他系统如 ElasticSearch 和 Kudu 等进行深度整合,具体的场景是假设已有 Talos Schema,基于 Talos Topic Schema 自动帮助用户创建 Kudu 表。
  • 平台化:为用户提供一体化、平台化的解决方案,包括调试开发、监控报警和运维等。

15.jpg

Job 管理

Job 管理提供 Job 全生命周期管理、Job 权限管理和 Job 标签管理等功能;支持Job 运行历史展示,方便用户追溯;支持 Job 状态与延迟监控,可以实现失败作业自动拉起。

16.jpg

SQL 管理

主要包括以下四个环节:

  • 将外部表转换为 SQL DDL,对应 Flink 1.9 中标准的 DDL 语句,主要包含 Table Schema、Table Format 和 Connector Properities。
  • 基于完整定义的外部 SQL 表,增加 SQL 语句,既可以得到完成的表达用户的需求。即 SQL Config 表示完整的用户预计表达,由 Source Table DDL、Sink Table DDL 和 SQL DML语句组成。
  • 将 SQL Config 转换成 Job Config,即转换为 Stream Job 的表现形式。
  • 将 Job Config 转换为 JobGraph,用于提交 Flink Job。

17.jpg

外部表转换成 SQL DDL 的流程如下图所示。

  • 首先根据外部表获取 Table Schema 和 Table Format 信息,后者用于反解数据,如对于 Hive 数据反序列化;
  • 然后再后端生成默认的 Connector 配置,该配置主要分为三部分,即不可修改的、带默认值的用户可修改的、不带默认值的用户必须配置的。

不可修改的配置情况是假设消费的是 Talos 组件,那么 connector.type 一定是 talos,则该配置不需要改;而默认值是从 Topic 头部开始消费,但用户可以设置从尾部开始消费,这种情况属于带默认值但是用户可修改的配置;而一些权限信息是用户必须配置的。

之所以做三层配置管理,是为了尽可能减少用户配置的复杂度。Table Schema、Table Format 和 Connector 1 其他配置信息,组成了SQL DDL。将 SQL Config 返回给用户之后,对于可修改的需要用户填写,这样便可以完成从外部表到 SQL DDL 的转换,红色字体表示的是用户修改的信息。

18.jpg

SQL 管理引入了一个 External Table 的特性。假设用户在平台上选择消费某个 Topic 的时候,该特性会自动地获取上面提到的 Table 的 Schema 和 Format 信息,并且显示去掉了注册 Flink Table 的逻辑;获取 Schema 时,该特性会将外部表字段类型自动转换为 Flink Table 字段类型,并自动注册为 Flink Tab 了。同时将 Connector Properties 分成三类,参数带默认值,只有必须项要求用户填写;所有参数均采用 Map 的形式表达,非常便于后续转化为 Flink 内部的 TableDescriptor。

18.jpg

上面介绍了 SQL DDL 的创建过程,在已经创建的 SQL DDL 的基础上,如 Source SQL DDL 和 Sink SQL DDL,要求用户填写 SQL query 并返回给后端,后端会对 SQL 进行验证,然后会生成一个 SQL Config,即一个 SQL 语句的完整表达。

18.jpg

SQL Config 转换为 Job Config 的流程如下图所示。

  • 首先在 SQL Config 的基础上增加作业所需要的资源、Job 的相关配置(Flink 的 state 参数等);
  • 然后将 SQLConfig 编译成一个 Job Descriptor,即 Job Config 的描述,如 Job 的 Jar 包地址、MainClass 和 MainArgs 等。

19.jpg

下图展示了 Job Config 转换为 Job Graph 的过程。对于 DDL 中的 Schema、Format 和 Property 是和 Flink 中的 Table Descriptor 是一一对应的,这种情况下只需要调用 Flink 的相关内置接口就可以很方便地将信息转换为 Table Descriptor,如 CreateTableSource()、RegistorTableSource() 等。通过上述过程,DDL 便可以注册到 Flink 系统中直接使用。对于 SQL 语句,可以直接使用 TableEnv 的 sqlUpdate() 可以完成转换。

20.jpg

SQL Config 转换为一个 Template Job 的流程如下所示。前面填写的 Jar 包地址即该 Template 的 Jar 地址,MainClass 是该 Template Job。假设已经有了 SQL DDL,可以直接转换成 Table Descriptor,然后通过 TableFactorUtil 的 findAndCreateTableSource() 方法得到一个 Table Source,Table Sink 的转换过程类似。完成前两步操作后,最后进行 sqlUpdate() 操作。这样便可以将一个 SQL Job 转换为最后可执行的 Job Graph 提交到集群上运行。

21.jpg

Talos Sink 采用了下图所示的三种模式:

  • Row:Talos 的数据原封不动地灌到目标系统中,这种模式的好处是数据读取和写入的时候无需进行序列化和反序列化,效率较高;
  • ID mapping:即左右两边字段进行 mapping,name 对应 field_name,timestamp 对应 timestamp,其中 Region 的字段丢掉;
  • SQL:通过 SQL 表达来表示逻辑上的处理。

22.jpg

未来规划

小米流式平台未来的计划主要有以下几点:

  • 在 Flink 落地的时候持续推进 Streaming Job 和平台化建设;
  • 使用 Flink SQL 统一离线数仓和实时数仓;
  • 在 Schema 的基础上数据血缘分析和展示,包括数据治理方面的内容;
  • 持续参与 Flink 社区的建设。

作者介绍:

夏军,小米流式平台负责人,主要负责流式计算,消息队列,大数据集成等系统的研发工作,主要包括 Flink,Spark Streaming,Storm,Kafka 等开源系统和一系列小米自研的相关系统。

相关实践学习
基于Hologres轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
Linux入门到精通
本套课程是从入门开始的Linux学习课程,适合初学者阅读。由浅入深案例丰富,通俗易懂。主要涉及基础的系统操作以及工作中常用的各种服务软件的应用、部署和优化。即使是零基础的学员,只要能够坚持把所有章节都学完,也一定会受益匪浅。
相关文章
|
5天前
|
Cloud Native 安全 API
云原生架构下的微服务治理策略与实践####
—透过云原生的棱镜,探索微服务架构下的挑战与应对之道 本文旨在探讨云原生环境下,微服务架构所面临的关键挑战及有效的治理策略。随着云计算技术的深入发展,越来越多的企业选择采用云原生架构来构建和部署其应用程序,以期获得更高的灵活性、可扩展性和效率。然而,微服务架构的复杂性也带来了服务发现、负载均衡、故障恢复等一系列治理难题。本文将深入分析这些问题,并提出一套基于云原生技术栈的微服务治理框架,包括服务网格的应用、API网关的集成、以及动态配置管理等关键方面,旨在为企业实现高效、稳定的微服务架构提供参考路径。 ####
25 5
|
8天前
|
监控 Go API
Go语言在微服务架构中的应用实践
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出,成为构建微服务的理想选择。本文将探讨Go语言在微服务架构中的应用实践,包括Go语言的特性如何适应微服务架构的需求,以及在实际开发中如何利用Go语言的特性来提高服务的性能和可维护性。我们将通过一个具体的案例分析,展示Go语言在微服务开发中的优势,并讨论在实际应用中可能遇到的挑战和解决方案。
|
6天前
|
负载均衡 监控 Cloud Native
云原生架构下的微服务治理策略与实践####
在数字化转型浪潮中,企业纷纷拥抱云计算,而云原生架构作为其核心技术支撑,正引领着一场深刻的技术变革。本文聚焦于云原生环境下微服务架构的治理策略与实践,探讨如何通过精细化的服务管理、动态的流量调度、高效的故障恢复机制以及持续的监控优化,构建弹性、可靠且易于维护的分布式系统。我们将深入剖析微服务治理的核心要素,结合具体案例,揭示其在提升系统稳定性、扩展性和敏捷性方面的关键作用,为读者提供一套切实可行的云原生微服务治理指南。 ####
|
6天前
|
消息中间件 缓存 Cloud Native
云原生架构下的性能优化实践与挑战####
随着企业数字化转型的加速,云原生架构以其高度解耦、弹性伸缩和快速迭代的特性,成为现代软件开发的首选模式。本文深入探讨了云原生环境下性能优化的关键策略与面临的主要挑战,通过案例分析,揭示了如何有效利用容器化、微服务、动态调度等技术手段提升应用性能,同时指出了在复杂云环境中确保系统稳定性和高效性的难题,为开发者和架构师提供了实战指南。 ####
20 3
|
6天前
|
运维 Kubernetes Cloud Native
深入理解云原生架构:从理论到实践
【10月更文挑战第38天】本文将引导读者深入探索云原生技术的核心概念,以及如何将这些概念应用于实际的软件开发和运维中。我们将从云原生的基本定义出发,逐步展开其背后的设计哲学、关键技术组件,并以一个具体的代码示例来演示云原生应用的构建过程。无论你是云原生技术的初学者,还是希望深化理解的开发者,这篇文章都将为你提供有价值的见解和实操指南。
|
6天前
|
Kubernetes Cloud Native 持续交付
云原生技术在现代应用架构中的实践与思考
【10月更文挑战第38天】随着云计算的不断成熟和演进,云原生(Cloud-Native)已成为推动企业数字化转型的重要力量。本文从云原生的基本概念出发,深入探讨了其在现代应用架构中的实际应用,并结合代码示例,展示了云原生技术如何优化资源管理、提升系统弹性和加速开发流程。通过分析云原生的优势与面临的挑战,本文旨在为读者提供一份云原生转型的指南和启示。
20 3
|
6天前
|
运维 Kubernetes Cloud Native
云原生技术在现代应用架构中的实践与挑战####
本文深入探讨了云原生技术的核心概念、关键技术组件及其在实际项目中的应用案例,分析了企业在向云原生转型过程中面临的主要挑战及应对策略。不同于传统摘要的概述性质,本摘要强调通过具体实例揭示云原生技术如何促进应用的灵活性、可扩展性和高效运维,同时指出实践中需注意的技术债务、安全合规等问题,为读者提供一幅云原生技术实践的全景视图。 ####
|
7天前
|
缓存 负载均衡 JavaScript
探索微服务架构下的API网关模式
【10月更文挑战第37天】在微服务架构的海洋中,API网关犹如一座灯塔,指引着服务的航向。它不仅是客户端请求的集散地,更是后端微服务的守门人。本文将深入探讨API网关的设计哲学、核心功能以及它在微服务生态中扮演的角色,同时通过实际代码示例,揭示如何实现一个高效、可靠的API网关。
|
5天前
|
Cloud Native 安全 数据安全/隐私保护
云原生架构下的微服务治理与挑战####
随着云计算技术的飞速发展,云原生架构以其高效、灵活、可扩展的特性成为现代企业IT架构的首选。本文聚焦于云原生环境下的微服务治理问题,探讨其在促进业务敏捷性的同时所面临的挑战及应对策略。通过分析微服务拆分、服务间通信、故障隔离与恢复等关键环节,本文旨在为读者提供一个关于如何在云原生环境中有效实施微服务治理的全面视角,助力企业在数字化转型的道路上稳健前行。 ####
|
6天前
|
Dubbo Java 应用服务中间件
服务架构的演进:从单体到微服务的探索之旅
随着企业业务的不断拓展和复杂度的提升,对软件系统架构的要求也日益严苛。传统的架构模式在应对现代业务场景时逐渐暴露出诸多局限性,于是服务架构开启了持续演变之路。从单体架构的简易便捷,到分布式架构的模块化解耦,再到微服务架构的精细化管理,企业对技术的选择变得至关重要,尤其是 Spring Cloud 和 Dubbo 等微服务技术的对比和应用,直接影响着项目的成败。 本篇文章会从服务架构的演进开始分析,探索从单体项目到微服务项目的演变过程。然后也会对目前常见的微服务技术进行对比,找到目前市面上所常用的技术给大家进行讲解。
17 1
服务架构的演进:从单体到微服务的探索之旅