共计 7577 个字符,预计需要花费 19 分钟才能阅读完成。
摘要:本文整顿自上海数⽲信息科技有限公司⼤数据架构师杨涵冰,在 Flink Forward Asia 2022 流批一体专场的分享。本篇内容次要分为六个局部:
- 序
- 传统计划与流批⼀体
- 数据的流批一体计划
- 逻辑的流批一体计划
- 数据一致性计划
- 流、批、调用一体计划
点击查看直播回放和演讲 PPT
一、序
1.1. 一些问题
咱们在整个实时流模型开发的过程中,常常会遇到一些问题:
- 在对现有模型策略精耕细作之前,还有没有什么数据没有被使⽤?
- 离线特色逻辑是否曾经⾜够残缺,为什么实时特色逻辑须要从新梳理与补充逻辑?
- 不确定使⽤场景,⽆法辨别点查和跑批,能不能同时笼罩?
- 流式解决逻辑难以了解,为什么要流 Join,不能间接“取数”吗?
- 实时模型策略空跑测试须要很⻓工夫,能不能缩短?
- 模型策略开发训练很快,上线时开发所需的实时特色却须要很久,能不能减速?特地是当咱们要进行一些深度学习模型开发的时候,咱们须要的实时数据会很多,且结构复杂,这个时候就更加难以使用传统实时特色的形式来进行解决。那么咱们要如何将它上线呢?
1.2. 一些计划
针对以上的问题,咱们提出了一些计划:
- 数据上,存储所有状态变动数据,还原任意时刻的数据切片状态。
- 逻辑上,应用 Flink 流批一体,以流为主,逻辑统一,无需验证口径。
- 执行上,应用流、批、调用一体化计划,自适应不同的场景。
- 开发上,应用“取数”而不是流合并,封装实时流特有概念,升高实时开发门槛。
- 测试上,反对任意时间段回溯测试,减少实时开发测试速度。
- 上线上,自助式的流批一体模型开发上线,缩小沟通环节,减少上线效率。
二、传统计划与流批一体
有两个很经典的传统计划别离是 Lambda 架构和 Kappa 架构。
Lambda 架构领有实时链路和离线链路两个不同的数据链路。其中,实时链路是一个实时作业,它会将数据实时写入 Serving DB。离线链路则是一个离线作业,它会通过批处理的形式将数据写入 Serving DB。最初线上利用通过 Serving DB 进行拜访。
Kappa 架构的实时链路和离线链路都应用了雷同的流式解决零碎,最初线上利用也是通过 Serving DB 进行拜访。
那么 Lambda 和 Kappa 有什么优缺点呢?
Lambda 架构的长处包含架构简略;很好的联合了离线批处理和实时流解决的长处;稳固且实时计算成本可控;离线数据易于勘误。毛病包含实时、离线数据难以保持一致后果,须要保护两套零碎。
Kappa 架构的长处包含只须要保护实时处理模块;能够通过音讯重放进行数据回溯;无需离线和实时数据合并。毛病包含强依赖于消息中间件缓存能力;实时数据处理时存在失落数据可能。
Kappa 在摈弃了离线数据处理模块的时候,同时也摈弃了离线计算更稳固牢靠的特点。Lambda 尽管保障了离线计算的稳定性,但双系统的保护老本高且两套代码的运维很艰难。
在数据源来自于 Kafka 的场景下,Kappa 看上去没有什么太多问题。但在互联网金融场景下,咱们次要的数据源都来自事务性数据,比如说 MySQL,它的实时流数据能够通过 Binlog 进行同步,但最终数据还是要以 MySQL 内存储的数据为准。如果应用 Kappa,整个链路就会变成一个纯增量链路,累积的误差将难以进行修改。此时咱们须要 Lambda 架构的离线修改能力。
咱们提出的计划是 Lambda+Kappa,右边是 Lambda,左边是 Kappa。
右边的 Lambda 局部,咱们以 MySQL 为例,MySQL 的 Binlog 会被同步到 Kafka,而后咱们将 Kafka 的音讯变动数据存入 HBase。同时它的全量数据会通过 Sqoop 抽取进入 EMR,通过 Spark 工作进行数据比照修改,而后将修改数据和切片数据存入 HBase。
左边的 Kappa 局部,也是咱们交给用户书写 Flink 的局部。须要留神一下,Flink 流解决和 Flink 批处理的代码是一样的。在实时流解决的过程中,Flink 它会间接生产 Kafka 的实时流数据,能够失去最低提早。在离线批处理的过程中,它的数据则来自于 HBase 的重放。
上图是流批一体计划的数据流。能够看到 MySQL 的 Binlog 进 Kafka,而后它的实时数据会通过数据同步进入事件核心,离线修改及切片也会每日同步进入事件核心。Flink 作业在实时触发过程中,通过 Kafka 来获取相干数据。在离线过程中,则通过事件核心获取相干数据,同时它也能够通过事件核心获取一些其余事件流的历史数据。最初由元数据中心进行对立的元数据服务。
三、数据的流批一体计划
实时运行时,咱们能够获取以后时刻各数据源的流水数据及切片状态数据。在离线剖析和回溯时,咱们能够通过获取回溯时刻各数据源流水的数据以及切片状态数据。此时实时和离线获取的数据结构及数据内容是齐全保持一致的。咱们通过标准化的时序数据接入与获取,这样能够人造杜绝穿梭问题。
咱们用事件核心承载了整个数据存储计划。首先应用 Lambda 架构存储所有变动数据,实时写入,离线修改。因为咱们存储的是所有变动数据,它的存储量会比拟大,所以咱们应用冷热混存与重加热机制来谋求最佳性价比。而后咱们仿造 Flink 的水印机制,在事件核心实现了一个特有的水印机制,确保以后值同步实现,从而能够以“取数”代替流 Join。
除此之外,咱们还提供了音讯转发机制。通过异步转同步反对触发音讯接管及触发轮询式调用,并赋予该接口回溯能力。这样无论通过音讯还是调用,咱们就都能够反对,且应用模型的开发人员也无需再关怀零碎对接细节。
MySQL 的 Binlog 会同步进 Kafka;Kafka 的数据就会被间接应用;RabbitMQ 音讯通过转发作业转发进 Kafka;音讯转发服务的 API 申请也会转发成 Kafka。接着由一个 Flink 作业去生产这些 Kafka 数据,并将其存到 HBase 热存。
此时 MySQL 会有一个额定的离线链路,通过 Sqoop 抽取到 EMR,进行快照与修改,而后将数据存进 HBase 热存。HBase 热存通过 replica 机制将数据同步到 HBase 冷存。当拜访到冷存数据时,会有一个从新加热的机制,把 HBase 冷存数据从新加热回热层。
从上图能够看到,HBase 热存里有四张表,其中第一张是主数据,上面三张是索引表,它用一个继续的构造进行存储。咱们在 HBase 热存中仅存储 32 天内的数据,超过这个工夫的数据须要通过冷存获取。
索引表里的第二张索引表(标记了 watermark 字样)就是咱们的用于实现索引机制的表。
当一个 Flink 作业在实时触发的时候,它实际上是间接应用的 Kafka 流数据,只是咱们通过元数据中心把相干的逻辑对立封装了。Flink 的使用者无需关怀数据是来自 Kafka 还是 HBase,因为对他来说是一样的。
在回溯的时候会主动应用 HBase 热存,如果读到冷存数据,它也会主动触发一个从新加热的机制。除此之外,当你须要间接取其余数据流数据的时候,也能够间接在 HBase 中取数。
咱们在实时流开发中常常比拟头疼的就是多流 Join。这里咱们以双流 Join 举个例子,多流 Join 是一样的,以此类推。
假如咱们要对两个流进行 Join,也能够简略了解为两张表,通过某外键进行行关联。当任何一张表产生变更时,咱们都须要至多触发一次最终残缺 Join 后的记录。
咱们将两个流别离记录为 A 和 B,并且假如 A 流先到。那么在关上事件核心水印机制的状况下,A 流触发时,A 流的以后事件曾经被记录在事件核心中。此时分为两种状况:
- 在工夫核心中能够取到 B 流的相干数据,那么阐明 A 流以后事件记录进事件核心,到运行至读取 B 流相干数据的时间段内,B 流曾经实现了事件核心的记录,此时的数据曾经残缺。
- 在事件核心中无奈取到 B 流的相干数据,那么因为事件核心水印机制,阐明此时 B 流相干事件尚未触发。而因为 A 流以后事件曾经被写入事件核心,那么当 B 流相干事件被触发时,肯定能取得 A 流的以后事件数据,此时数据也是残缺的。
由此,通过事件核心水印机制,即可确保用“取数”取代流 Join 后至多会有一次领有残缺数据的计算。
转发机制次要是为了对一些传统零碎进行兼容,它分为两种。第一种是触发音讯接管式,比方内部零碎发动一个申请,咱们的音讯转发零碎接管到申请后,会把申请转发成一个 Kafka 音讯,并且将音讯存到事件核心中。
之后 Flink 作业接管到 Kafka 音讯后会进行运算,并将后果发送到 RabbitMQ 等用户可能间接订阅的音讯零碎中,而后内部零碎接管相干的音讯后果进行后续的操作。
第二种是触发轮询式,内部零碎会发动申请并轮询后果。这里须要留神一点,当解决工夫小于单次申请超时工夫的时候,轮询的动作就会进化为单次同步申请。这里和之前的计划是一样的,区别是 Flink 作业会将数据写入到一个 Kafka,而后由事件核心获取 Kafka 数据并进行存储,最初提供相干的服务。
通过这种形式咱们还额定使咱们的接口具备了数据回溯能力。
四、逻辑的流批一体计划
逻辑的流批一体是由 Flink 天生带来的,它能够使离线开发试运⾏与实时执⾏、离线回溯代码齐全⼀致。另外,咱们封装了实时流特有的概念,升高实时开发门槛。封装了简单的触发逻辑和简单的“取数”逻辑。
除此之外,咱们能够提供自助式的开发上线,缩小沟通环节,减少上线效率。最初咱们额定提供了热更新的参数,并反对独立的参数变更流程。使模型策略人员和经营人员有更好的交互。
咱们应用的 PyFlink,咱们应用它是起因模型策略人员通常应用 Python 进行相干的逻辑开发。
从上图咱们能够看到,整个代码被分为三个局部:触发、主逻辑、输入。触发局部咱们能够援用一些曾经封装好的触发逻辑,主逻辑局部咱们也能够援用一些曾经封装好取数,或者其余函数逻辑,输入局部咱们也能够援用一些曾经封装好的输入逻辑,同时咱们也反对多路输入。
上图展现的是整体数据流,首先触发逻辑会触发到主逻辑,主逻辑能够引入一些取数逻辑,最初会有一个输入逻辑。模型策略人员次要开发的是主逻辑,对于触发逻辑、取数逻辑、输入逻辑个别间接抉择就能够了。
触发逻辑、取数逻辑、输入逻辑,它的底层封装会随着流批环境主动变动,同时确保输出和输入不变。逻辑自身在绝大多数状况下不须要思考流批环境的变动,当然在某些非凡状况也是须要思考的。而由模型策略人员开发的主逻辑局部则齐全无需思考流批环境变动,曾经被齐全封装好了。
热更新参数操作流分为两个角色:模型人员、经营人员。模型人员须要定义一些参数,并对这些参数进行阐明,最初在代码中应用这些参数。经营人员须要去浏览参数的定义及参数的阐明,而后进行相干变更的提交,最初通过审核进行失效。
咱们依照分工和职能能够把整个零碎分为三类人:
- 第一类是平台管理人员,他能够规整化并接入数据源;封装触发事件和“取数”逻辑;封装输入链路;封装并标准化场景。
- 第二类是模型人员,他能够抉择触发事件、“取数”逻辑或间接应用标准化场景;抉择一种或多种输入链路,输入运行后果。
- 第三类是经营人员,他能够观测模型运行后果;热更新模型参数。
站在模型策略人员的视角,典型的应用流程为如下操作:
- 第一步,须要抉择一个触发流。
- 第二步,编写取数和预处理逻辑,也能够间接引入曾经公布的取数或解决逻辑代码。
- 第三步,设置回溯逻辑并试运行,它能够依照样本表或工夫切片进行回溯。
- 第四步,获取试运行后果,在剖析平台中进一步剖析与训练。
- 第五步,训练实现后公布模型,在作业中抉择训练实现的模型。如果有须要,能够设置热更新参数及初始化相干参数。
- 第六步,公布作业,上线实现。
整个过程自助化十分高,能够缩小很多沟通环节,疾速训练、测试、公布模型。
五、数据一致性计划
实时流解决是一种异步解决形式,如果没有非凡需要一致性级别个别均为最终统一,但也能够通过一些额定计划来实现更高的一致性要求。分为以下四种计划:
- 最终统一:通过一段时间后能拜访到更新的数据。整个流批一体计划默认保障最终统一。
- 触发流强统一(可提早):它会保障触发流重的以后数据及早于以后的数据,在对触发流的取数过程中能取到。应用水印计划,当水印不满足时进行提早。
- 取数强统一(可提早):它会保障取数时早于用户提出工夫要求的数据均能取到。应用水印计划,水印不满足时进行提早。
- 取数强统一(无提早):它会保障取数时早于用户提出工夫要求的数据均能取到。当水印不满足时,它会间接从数据源增量补足。这里须要留神,增量取数会对数据源带来压力,要审慎。
从上图咱们能够看到,数据源触发了一个事件。因为它是一个异步零碎,它会同时触发事件核心的存储作业和 Flink 生产的作业,所以当 Flink 生产的时候它有可能读不到事件核心当次事件的存储。事件核心没有实现写入就取不到数据,只有当事件核心实现写入的时候,能力取到最新的数据。
整体的时序和最终统一时序一样,区别在于 Flink 作业会进行事件核心水印机制的判断。如果不满足,它会进行提早,直至满足相干的水印机制,就能取得最新的数据了。
取数强统一(可提早)时序和最终统一时序也很相似,只是因为是取数流,所以它触发的 Kafka 和数据的 Kafka 是离开的。他的解决计划也是通过事件核心的水印机制,如果不满足就提早直至满足,能力获取相干的数据。
前半部分和最终统一时序一样,但它在水印机制不满足的时候,就不再期待和提早了,它会间接从数据源增量获取数据。显然,这种状况会对数据源造成压力,因而这种状况要审慎。
在绝大多数场景,比方反欺诈、经营等对时效性并没有那么敏感的场景下,最终统一曾经足够满足需要了,这也是咱们实际中绝大多数状况应用的形式。
触发流强制统一(可提早)是在对触发流统计误差要求很高的场景下应用。个别除了状态初始化外,咱们也能够间接应用 Flink 自带的 state 机制来解决。
取数强统一(可提早),它在对取数流统计误差要求很高的状况下应用。比方一些金融场景下,须要对全历史订单进行统计,那么就要求不能有误差,所以就须要用这种形式。
取数强统一(无提早),因为会对数据源造成外的压力,这个计划只会在极少状况下应用。个别对时效性要求有如此高的时候,咱们会优先思考间接在线上利用解决。只有在线上利用无奈解决的大数据量状况下才会思考应用,个别极少应用。
六、流、批、调用一体计划
在模型策略上线后,咱们必然要通过某种形式能力为线上零碎提供服务。对不同的调用形式进行封装,咱们能够在模型策略代码不批改的前提下,自适应各类不同场景的调用需要。次要分为以下四种:
- 第一种,特色存储服务计划。在 Flink 作业进行预运算当前,将运算后果写入特色存储服务平台,并通过该数据服务平台对外服务。
- 第二种,接口触发 – 轮询计划。它调用并轮询事件核心的音讯转发接口,直到 Flink 作业返回运算后果。
- 第三种,接口触发 – 音讯接管计划。它调用事件核心的音讯转发接口来触发 Flink 作业运算,接管 Flink 作业返回的运算后果音讯。
- 第四种,间接音讯承受计划。线上零碎无需关怀触发,间接应用 Flink 作业返回的运算后果音讯进行相干的运算。
从上图中在两头能够看到有三个 Flink,这三个 Flink 节点的代码是一样的,不须要批改,就是同一个作业。
整个数据流竖着看咱们分成三条线。
第一条是实时,它就是 Kafka 的实时触发。触发 Flink 代码,而后运算后果会存 Kafka,最初存储到特色存储。
第二条和第三条都是离线,别离是离线初始化和离线修改。它们都是通过事件核心 HBase 来批量触发 Flink 工作,而后将后果写入 EMR,EMR 将数据同步进特色存储。
除此之外,如果对其余流提出一些需要,不论是实时还是离线,都能够从事件核心的 HBase 中进行取数。
咱们须要留神一下,特色存储服务计划因为是一个预运算的异步计划,所以它的时效性和一致性需要也是最终统一。从上图咱们能够看到,Kafka 触发当前会进行运算,而后写入到特色存储。如果内部调用太早,Flink 作业还没实现运算以及写入特色存储,就无奈获取更新的数据,只有等到 Flink 作业运行结束,并写入了特色存储系统,能力失去更新的数据。
这是通过一种异步转同步的形式将一个异步的 Flink 作业变成同步的申请。内部零碎通过申请触发来调用咱们的音讯转发机制,音讯转发机制会将音讯转发到 Kafka 触发 Flink 的运算,Flink 运算结束会将数据写进写进 Kafka,最初写进事件核心 HBase。
须要留神一下,如果整个过程没有超过单次申请的超时工夫,那么此时触发轮询会进化为单次触发的同步调用,即变成一个简略的同步调用。如果超过了,就须要触发方进行轮询,通过事件查问查问事件核心的 HBase 是否有后果。
从上图能够看到,内部调用会触发音讯转发与查问服务,而后音讯转发与查问服务会触发一个事件,Flink 会生产这个事件并进行相干计算,最初写进事件核心。同时音讯转发与查问服务会一直尝试从事件核心获取运算后果,如果始终获取失败,第一次的调用就会超时,须要你第二次轮询,直到轮询到计算结果。这是一种异步转同步的形式。
后面是一样的,音讯转发转发到 Flink 作业,但 Flink 就不再写进 Kafka 了,会间接写到内部零碎可能应用的音讯零碎中。而后内部零碎进行相应的事件监听,获取运行后果。
整个数据流就会变得比后面的时序简略很多,它就是一个十分传统的异步调用时序,只是两头会有一个音讯转发服务会帮你把同步申请转发成音讯来触发计算。
这个就比拟传统,内部零碎无需关怀触发流,触发流会由作业自行应用。Flink 作业接管触发并运算结束后,将后果间接写到 RabbitMQ 等内部零碎可能接管的音讯队列,而后内部零碎会间接生产音讯并进行订阅接管,进行后续操作。
这是一个十分典型的异步时序,全程异步,数据流从 Kafka 到 Flink 到 RabbitMQ 最初到内部订阅。
流、批、调用一体化提供的服务计划:
- 特色存储服务计划。通过特色存储服务提供长久化的特色存储,提供 API 点查及特色圈选服务。
- 接口触发—轮询计划。通过事件核心的音讯转发与音讯查问服务,将同步调用转换成异步音讯解决,最初对外封装的时候就是一个简略的同步申请。
- 接口触发—音讯接管计划。通过事件核心的音讯转发服务,与接口触发—轮询计划的区别是最终提供的是音讯,将音讯发回相干的利用零碎。
- 间接音讯接管计划。反对简单的事件触发,提供事件音讯服务。
咱们以 Flink 作为外围引擎,以事件核心作为中间层以及存储,使调用、实时流、离线跑批都能够用雷同的形式来进行解决。这样模型、策略无论被如何应用,都无需批改即可执行。
点击查看直播回放和演讲 PPT
更多内容
流动举荐
阿里云基于 Apache Flink 构建的企业级产品 - 实时计算 Flink 版现开启流动:
99 元试用 实时计算 Flink 版(包年包月、10CU)即有机会取得 Flink 独家定制卫衣;另包 3 个月及以上还有 85 折优惠!
理解流动详情:https://www.aliyun.com/product/bigdata/sc