TikTok的主要收入来自直播和电商,这要求实时处理数据,比批处理更复杂,涉及多流连接和维度表更新,需要更多开发和维护资源,且为保障系统稳定,常导致资源浪费。本文邀请了TikTok数据平台团队分享他们如何利用Apache Doris构建实时数据架构,可作为高效实时数据仓库的范例学习。
1. TikTok的实时数据仓库
图片
在迁移到Apache Doris前,TikTok通过Flink传输实时数据,并使用Kafka在不同数据层间实现数据流动。由于Kafka本身没有逻辑表,因此在其上开发不如在Hive上那么容易。对于TikTok来说,实时数据与离线数据之间的数据量存在显著差距。由于与实时数据相关的开发、运营和资源成本,团队倾向于降低实时数据的要求,但这只是一种临时的解决方案。
- 开发成本:由于Flink是一个具有增量状态的状态化数据流引擎,它要求开发者对底层架构有更深入的了解,尤其是在多流JOIN操作中。增量状态使其无法像Hive那样将完整的数据状态存储到内存。实时数据需要巨大的存储容量,并且需要使用各种计算引擎(例如OLTP引擎MySQL,OLAP引擎ClickHouse和Apache Doris,以及KV存储Abase、Tier和Redis)满足不同的计算需求,这增加了开发的复杂性。增量状态也使得测试更具挑战性。
- 维护成本:复杂的多流JOIN操作通常需要存储大量状态数据,这可能导致稳定性问题,特别是在处理连续的实时流时。TikTok的直播业务在不断创新。当数据模式发生变化时,直接部署可能因状态结构的改变而导致数据恢复失败。
- 资源问题:在实时场景中,资源的低效利用是一个常见问题。例如,在销售活动开始时,通常会有短暂的流量激增,但几分钟后流量会迅速下降。然而,为了确保整个活动期间的稳定性,必须全天候维持高水平的资源,这导致了资源的浪费。
图片
基于Flink的架构在TikTok中已是一个成熟的解决方案。它主要用于成熟的业务应用。在数据存储方面,它利用Kafka提供的逻辑表格式。尽管缺乏字段、约束和高数据可追溯性,这种逻辑表方法仍支持了超过一半的实时数据开发。
新的架构基于Apache Doris,结构更简单,类似于离线Hive设置。这种基于Doris的架构的关键在于将亚秒级调度引擎与OLAP引擎相结合。这使得数据分层和重用离线开发成为可能。
2. OLAP引擎
为服务于TikTok的直播业务,OLAP引擎应在以下方面表现良好。
- 跨站点灾难恢复:这为直播提供了稳定性保证,以避免因服务不可用而导致的重大财务损失。
- 读写隔离:这是稳定性的另一个保障。
- 跨集群ETL:数据分散在不同的集群中,用于不同的业务场景。例如,集群 B 和 C 都处理交易数据,这些数据应该从集群 B 同步到 C,否则会导致跨业务线的数据仓库重复建设,并对人力和资源造成负担。
图片
TikTok解决这些挑战的方式如下。
- 跨站点灾难恢复:每个表都存储了三个副本。这些副本分布在数据中心中,以确保每个站点的可用性。生产端的消息队列经过中间处理后到达消费端,形成了完整的数据服务链路。在单个数据中心中断的情况下,生产和消费都有相应的策略来确保服务效率和稳定性。
- 读写隔离:读写流量被路由到不同的集群组。
- 跨集群 ETL:对于跨集群的读写,TikTok根据不同的业务需求和时间敏感性采用了两种机制。一种是使用Spark将数据源格式读入Yarn集群,然后同步到其他集群。另一种是利用Apache Doris的跨集群复制能力。Spark on Doris方法更稳定,不消耗Doris的计算资源,而第二种方法更高效。
3. 实时排行榜
实时数据仓库如何支持TikTok的直播业务?
它构建了一个实时排行榜来监测其直播业务的表现。如前所述,它从Flink 迁移到了Apache Doris,新方案对元数据有明确的定义。元数据从实时表中的字段解析而来并给出定义。定义元数据是对排行榜业务逻辑的抽象。这还涉及实时排行榜的分区逻辑定义。通过简单的配置,可以快速创建相应的Flink任务。
图片
然而,对这种实时排行榜的需求激增,对Flink架构带来了几方面的挑战。首先,过多的排行榜导致任务激增,使得资源管理更困难,尤其是需要24/7运行的实时流处理。其次,来自实时任务的警报越来越频繁。此外,大量任务共享同一消息队列,增加了流量,给HDFS带来了额外的负担。此外,由于电商中的大型促销活动往往持续较长时间,长周期计算对Flink的稳定性构成威胁,也使得回溯变得困难。为解决这些问题,维护人员通常需要在状态相对较小、回溯压力较轻的午夜进行操作。
与Flink的解决方案相比,基于Doris的数据仓库消耗的资源更少,产生的警报也更少。此外,由于状态存储在Doris表中,长周期计算变得更加灵活。