关于Flink:汽车之家基于-Apache-Flink-的跨数据库实时物化视图探索

24次阅读

共计 5782 个字符,预计需要花费 15 分钟才能阅读完成。

本文介绍了汽车之家在基于 Flink 的实时物化视图的一些实践经验与摸索,并尝试让用户间接以批处理 SQL 的思路开发 Flink Streaming SQL 工作。次要内容为:

  1. 系统分析与问题拆解
  2. 问题解决与零碎实现
  3. 实时物化视图实际
  4. 限度与有余
  5. 总结与瞻望

前言

物化视图这一性能想必大家都不生疏,咱们能够通过应用物化视图,将事后设定好的简单 SQL 逻辑,以增量迭代的模式实时 (依照事务地) 更新后果集,从而通过查问后果集来防止每次查问简单的开销,从而节省时间与计算资源。事实上,很多数据库系统和 OLAP 引擎都不同水平地反对了物化视图。另一方面,Streaming SQL 自身就和物化视图有着很深的分割,那么基于 Apche Flink (下称 Flink) SQL 去做一套实时物化视图零碎是一件非常自然而然的事件了。

本文介绍了汽车之家 (下称之家) 在基于 Flink 的实时物化视图的一些实践经验与摸索,并尝试让用户间接以批处理 SQL 的思路开发 Flink Streaming SQL 工作。心愿能给大家带来一些启发,独特摸索这一畛域。

一、系统分析与问题拆解

Flink 在 Table & SQL 模块做了大量的工作,Flink SQL 曾经实现了一套成熟与绝对齐备的 SQL 零碎,同时,咱们也在 Flink SQL 上有着比拟多的技术和产品积攒,间接基于 Flink SQL 自身就曾经解决了构建实时物化零碎的大部分问题,而惟一一个须要咱们解决的问题是如何不重不漏地生成数据源表对应的语义齐备的 Changelog DataStream,包含增量和全量历史两局部。

尽管规约到只剩一个问题,然而这个问题解决起来还是比拟艰难的,那咱们将这个问题持续拆解为以下几个子问题:

1.  加载全量数据;2.  加载增量数据;3.  增量数据与全量数据整合。

二、问题解决与零碎实现

问题一:基于数据传输平台的增量数据读取

增量数据加载还是绝对比拟好解决的,咱们间接复用实时数据传输平台的根底建设。数据传输平台[1] 曾经将 Mysql / SqlServer / TiDB 等增量数据以对立的数据格式写入到特定的 Kafka Topic 中,咱们只有获取到对应的 Kafka Topic 就能够进行读取即可。

问题二:反对 checkpoint 的全量数据加载

对于全量数据载入,咱们先后写了两个版本。

第一版咱们用 Legacy Source 写了一套 BulkLoadSourceFunction,这一版的思路比拟奢侈,就是全量从数据源表进行查问。这个版本的确能实现全量数据的加载,然而问题也是比拟显著的。如果在 bulk load 阶段作业产生了重启,咱们就不得不从新进行全量数据加载。对于数据量大的表,这个问题带来的结果还是比较严重的。

对于第一版的固有问题,咱们始终都没有特地好的对策,直到 Flink-CDC[2] 2.0 的公布。咱们参考了 Flink-CDC 的全量数据加载阶段反对 Checkpoint 的思路,基于 FLIP-27 开发了新的 BulkLoadSource。第二版不管在性能上还是可用性上,比照第一版都有了大幅晋升。

问题三:基于全局版本的轻量 CDC 数据整合算法

这三个子问题中,问题三的难度是远大于后面两个子问题的。这个问题的奢侈思路或者很简略,咱们只有依照 Key 缓存全副数据,而后依据增量数据流来触发 Changelog DataStream 更新即可。

事实上咱们也曾依照这个思路开发了一版整合逻辑的算子。这版算子对于小表还是比拟 work 的,然而对于大表,这种思路固有的 overhead 开始变得不可承受。咱们曾用一张数据量在 12 亿,大小约 120G 的 SqlServer 表进行测试,自身就微小的数据再加上 JVM 上不可避免的收缩,状态大小变得比拟夸大。通过这次测试,咱们统一认为这样粗放的策略仿佛不适宜作为生产版本公布,于是咱们不得不开始从新思考数据整合的算法与策略。

在议论咱们的算法设计思路之前,我不得不提到 DBLog[3] 的算法设计, 这个算法的外围思路利用 watermark 对历史数据进行标识,并和对应的增量数据进行合并,达到不应用锁即可实现整个增量数据和历史数据的整合,Flink-CDC 也是基于这个思路进行的实现与改良。在相干材料收集和剖析的过程中,咱们发现咱们的算法思路与 DBLog 的算法的外围思路十分类似, 然而是基于咱们的场景和状况进行了设计与特化。

首先剖析咱们的状况:

  • 增量数据须要来自于数据传输平台的 Kafka Topic;
  • 增量数据的是 at least once 的;
  • 增量数据是存在 全序版本号 的。

联合上述情况进行剖析,咱们来规约一下这个算法必须要达成的指标:

  • 保证数据的 Changelog Stream,数据残缺,Event (RowKind) 语义齐备
  • 保障该算法的 overhead 是可控的;
  • 保障算法实现的解决性能是足够高效;
  • 保障算法实现 不依赖 任何来自于 Flink 内部的零碎或者性能。

通过大家的剖析与探讨后,咱们设计出了一套数据整合的算法,命名为 Global Version Based Pause-free Change-Data-Capture Algorithm

3.1 算法原理

咱们 同时 读入 BulkLoadSource 的全量数据与 RealtimeChangelogSource 增量数据,并依据主键进行 KeyBy 与 Connect,而算法的外围逻辑次要由之后的 KeyedCoProcess 阶段实现。上面交待几个要害的字段值:

  • SearchTs:全量数据从数据源 查问 进去的工夫戳;
  • Watermark:基于增量数据在 数据库里产生的工夫戳 生成;
  • Version:全序版本号,全量数据是 0,即肯定最小版本。

KeyedCoProcess 收到全量数据后,不会间接发送,而是先缓存起来,等到 Watermark 的值大于该 SearchTs 后发送并革除对应 version0 版本数据的缓存。在期待的期间,如果有对应的 Changlog Data,就将被缓存的 Version0 全量数据抛弃,而后解决 Changelog Data 并发送。在整个数据处理的流程中,全量数据和增量数据都是同时进行生产与解决的,齐全不须要引入暂停阶段来进行数据的整合。

             增量数据在全量数据发送 watermark 之前到来,只发送增量数据即可,全量数据间接抛弃        


             全量数据发送 watermark 达到后,仍未有对应的增量数据,间接发送全量数据


3.2 算法实现

咱们决定以 Flink Connector 的模式发展算法的实现,咱们以接入 SDK 的名字 Estuary 为该 Connector 命名。通过应用 DataStreamScanProvider,来实现 Source 外部算子间的串联,Source 的算子组织如下图 (chain 到一起的算子已拆开展现)。

  • BulkLoadSource / ChangelogSource 次要负责数据的读入和对立格局解决;
  • BulkNormalize / ChangelogNormalize 次要是负责解决数据运行时信息的增加与笼罩,主键语义解决等工作;
  • WatermarkGenerator 是针对算法工作需要定制的 Watermark 生成逻辑的算子;
  • VersionBasedKeyedCoProcess 就是外围的解决合并逻辑和 RowKind 语义齐备性的算子。

算法实现的过程中还是有很多须要优化或者进行衡量的点。全量数据进入 CoProcess 数据后,会首先查看以后是否解决过更大版本的数据,如果没有的话才进行解决,数据首先会被存入 State 中并依据 SearchTs + T (T 是咱们设置的固有时延) 注册 EventTimeTimer。如果没有高版本的数据到来,定时器触发发送 Version 0 的数据,否则间接摈弃改为发送 RowKind 语义解决好的高版本增量数据。

另一方面,防止状态的有限增长,当零碎断定 BulkLoad 阶段完结后,会完结对相干 Flink State 的应用,存在的 State 只有期待 TTL 过期即可。

另外,咱们针对在数据同步且上游 Sink 反对 Upsert 能力的场景下,开发了特地优化的超轻量模式,能够以超低的 overhead 实现全量 + 增量的数据同步

开发实现后,咱们的重复测试批改与验证,实现 MVP 版本的开发。

三、实时物化视图实际

MVP 版本公布后,咱们与用户同学一起,进行了基于 Flink 的物化视图试点。

1. 基于多数据源简单逻辑的 Data Pipeline 实时化

上面是用户的一个实在生产需要:有三张表,别离来自于 TiDB /。SqlServer / Mysql,数据行数别离为千万级 / 亿级 / 千万级,计算逻辑绝对简单,波及到去重,多表 Join。原有通过离线批处理产生 T+1 的后果表。而用户心愿尽可能升高该 Pipeline 的提早。

因为咱们应用的 TiCDC Update 数据尚不蕴含 -U 局部,故 TiDB 表的整合算法还是采取 Legacy Mode 进行加载。

咱们与用户沟通,倡议他们 以批处理的思路去编写 Flink SQL,把后果的明细数据的数据输入到 StarRocks 中。用户也在咱们的帮助下,较为疾速地实现了 SQL 的开发,工作的计算拓补图如下:

后果是相当让人惊喜的!咱们胜利地在保障了数据准确性的状况下,将原来天级提早的 Pipeline 升高至 10s 左右的提早。数据也从原来查问 Hive 变为查问 StarRocks,不管从数据接入,数据预计算,还是数据计算与查问,实现了全面的实时化。另一方面,三张表每秒的增量最大不超过 300 条,且该工作不存在更新放大的问题,所以资源应用相当的少。依据监控反馈的信息,初始化阶段实现后,整个工作 TM 局部只须要应用 1 个 Cpu (on YARN),且 Cpu 应用常态不超过 20%。比照原来批处理的资源应用,无疑也是微小晋升。

2. 数据湖场景优化

正如上文提到的,对于数据同步,咱们做了专门的优化。只须要应用专用的 Source 表,就能够一键开启历史数据 + 增量数据数据同步,大大简化了数据同步的流程。咱们目前尝试应用该性能将数据同步至基于 Iceberg 的数据湖中,从数据同步层面大幅晋升数据新鲜度。

四、限度与有余

尽管咱们在这个方向的摸索获得了肯定成绩,然而仍有肯定的限度和有余。

1. 服务器时钟的隐式依赖

仔细阅读下面算法原理,咱们会发现,不论是 SearchTs 的生成还是 Watermark 的生成,实际上最初都依赖了服务器零碎的时钟,而非依赖 相似 Time Oracle 机制。咱们尽管算法实现上引入固有提早去躲避这个问题,然而如果服务器呈现十分重大时钟不统一,超过固有提早的话,此时 watermark 是不牢靠的,有可能会造成解决逻辑的谬误。

经确认,之家服务器时钟会进行校准操作。

2. 一致性与事务

事实上咱们目前这套实现没有任何事务相干的保障机制,仅能承诺后果的最终一致性,最终一致性其实是一种相当弱的保障。就拿上文提到的例子来说,如果其中一张表存在 2 个小时的生产提早,另一张表根本不存在提早,这个时候两表 Join 产生的后果其实是一种中间状态,或者说对于内部零碎应该是不可见的。

为了实现更高的一致性保障,防止下面问题的产生,咱们天然会想到引入事务提交机制。然而目前咱们临时没有找到比拟好的实现思路,然而能够探讨下咱们目前的思考。

2.1 如何定义事务

事务这个概念想必大家或多或少都有意识,在此不多赘述。如何数据库系统外部定义事务是一件特地天然且必要的事件,然而如何在这种跨数据源场景下定义事务,其实是一件十分艰难的事件。还是以上文的例子来开展,咱们能看到数据源来自各种不同数据库,咱们其实对于单表记录了对应的事务信息,然而的确没有方法定义来自不同数据源的对立事务。咱们目前的奢侈思路是依据数据产生的工夫为基准,联合 checkpoint 对立划定 Epoch,实现相似 Epoch-based Commit 的提交机制。然而这样做又回到后面提到的问题,须要对服务器工夫产生依赖,无奈从本源保障正确性。

2.2 跨表事务

对于 Flink 物化视图一致性提交这个问题,TiFlink[4] 曾经做了很多相干工作。然而咱们的 Source 来自不同数据源,且读取自 Kafka,所以问题变得更为简单,还是下面提到的例子,两张表 Join 过后,如果想保障一致性,不只是 Source 和 Sink 算子,整个关系代数算子体系都须要思考引入事务提交的概念和机制,从而防止中间状态的对外部零碎的公布。

3. 更新放大

这个问题其实比拟好了解。当初有两张表 join,对于左表的每一行数据,对应右表都有 n (n > 100) 条数据与之对应。那么当初更新左表的任意一行,都会有 2n 的更新放大。

4. 状态大小

目前整套算法在全量同步阶段的 Overhead 尽管可控,然而仍有优化空间。咱们目前实测,对于一张数据量在 1 亿左右的表,在全量数据阶段,须要峰值最大为 1.5G 左右的 State。咱们打算在下个版本持续优化状态大小,最间接的思路就是 BulkSource 告诉 KeyedCoProcess 哪些主键汇合是曾经处理完毕的,这样能够使对应的 Key 提前进入全量阶段实现模式,从而进一步优化状态大小。

五、总结与瞻望

本文剖析了基于 Flink 物化视图实现的问题与挑战,着重介绍了解决生成残缺的 Changelog DataStream 的算法与实现和在业务上的收益,也充沛论述了目前的限度与有余。

尽管这次实际的后果称不上齐备,存在一些问题亟待解决,然而咱们仍看到了微小的冲破与提高,不论是从技术还是业务应用上。咱们充沛置信将来这项技术会越来越成熟,越来越被更多人认可和应用,也通过此次摸索充沛验证了流解决和批处理的统一性。

咱们目前的实现还处在晚期版本,仍有着工程优化和 bug fix 的空间与工作 (比方前文提到的两表的推动的 skew 太大问题,能够尝试引入 Coordinator 进行调节与对齐),然而置信随着一直的迭代与倒退,这项工作会变得越来越巩固,从而撑持更多业务场景,充沛晋升数据处理的品质与效率!

特地鸣谢张茄子和云邪老师的帮忙与勘误。

援用

[1] http://mp.weixin.qq.com/s/KQH…

[2] http://github.com/ververica/f…

[3] http://arxiv.org/pdf/2010.125…

[4] http://zhuanlan.zhihu.com/p/4…


更多 Flink 相干技术问题,可扫码退出社区钉钉交换群;

第一工夫获取最新技术文章和社区动静,请关注公众号~

正文完
 0