共计 3708 个字符,预计需要花费 10 分钟才能阅读完成。
一、背景
本次赛题思路源自于实在工作场景的一个线上我的项目,该我的项目在通过一系列优化后已稳固上线,在该我的项目开发的过程中数据平台组和技术负责人提供了许多资源和领导意见,而我的项目的后果也让我意识到了流计算在理论生产中优化的作用,进而加深了我对大数据利用的了解。
1.1 成员简介
陆冠兴:数据开发工程师,目前在互联网券商大数据部门工作,次要负责业务数据开发、数据平台建设、数据资产建设等相干工作,对流计算利用开发有肯定教训。
1.2 内容概述
本次赛题的次要内容,是通过引入流计算引擎 Flink+ 音讯队列 Kafka,应用 ETL 模式取代原有架构的 ELT 模式计算出用户的实时资产,解决原有架构下计算和读取压力大的问题,实现存算拆散;并以计算结果进一步做为数据源构建实时资产走势等数据利用,体现了更多的数据价值。
1.3 一些概念
在股票交易零碎中,用户须要先进行开户失去一个账户,该账户蕴含账户现金和账户持仓两局部,之后就能够通过该账户进行流水操作,同时也可进交易操作。
流水
- 出入金流水 = 往账户现金中存入 / 取出现金
- 出入货流水 = 往账户持仓中存入 / 取出股票
交易
- 买入股票 = 现金缩小,股票持仓减少
- 卖出股票 = 现金减少,股票持仓缩小
总资产的计算
- 用户总资产 = 账户现金 + 账户持仓股票市值
- 账户持仓股票市值 = 所持仓股票数量 * 对应的最新报价(实时变动)
1.4 传统架构的实现 & 痛点
当应用传统业务架构解决一个总资产的查问接口时,大抵须要通过的步骤如下:
- 用户从客户端发动资产申请到后端
- 后端过程去业务 DB 里查问所有用户现金表、用户持仓股票表以及最新股票报价表数据
- 后端过程依据查问到的数据计算出用户持仓的市值,加上用户现金失去出用户最新总资产
- 将算出的总资产后果返回客户端展现
但随着申请量的减少,在该架构下数据库和计算性能都会很快达到瓶颈,次要起因是下面的第 2 步和第 3 步的计算流程较长并且未失去复用:
- 每次客户端的申请到来时,后端过程都须要向业务的 DB 发动多个查问申请去查问表,这个对于数据库是有肯定压力
- 查问失去的数据库数据还须要计算能力失去后果,并且每来一个申请触发计算一次,这样的话 CPU 开销很大
二、技术计划
2.1 ETL 的架构 & 流计算
这里一个更正当的架构计划是应用 ETL 的架构对此做优化。
对于 ELT 架构,次要体现在 T(转换) 的这个环节的程序上,ELT 是最初再做转换,而 ETL 是先做转换它的长处是因为先做了转换,可能不便上游间接复用计算的后果。
那么回到总资产计算的这个例子,因为它的根本计算逻辑确定,而上游又有大量的查问需要,因而这个场景下适宜把 T 前置,也就是采纳 ETL 的架构。
在应用 ETL 架构的同时,这里抉择了 Flink 作为流计算引擎,因为 Flink 能带来如下益处:
- 仅在对应上游数据源有变更时触发算出对应的计算,防止了像批计算每个批次都须要去拉取全量数据源的开销
- 因为是事件触发计算最新的后果,所以实时性会比批计算会好很多
那么新的架构实现能够大抵如图,首先这里图中左边局部,通过引入 Flink 可先把计算的后果写到两头的数据仓库中;再把这个已算好数据提供给图中右边接口进行一个查问,并且因为数据仓库外面曾经是算好的后果,所以接口简直能够间接读取外面的数据无需再解决。
2.2 架构实现
实现这里次要分为三局部:数据接入、数据 ETL、提供数据。
2.2.1 数据接入
出于性能和 SQL 化的能力以及对 Flink 的兼容性思考,这里次要应用的接入计划是 Flink CDC,整个 SQL 局部只须要确定数据源实例和库表的一些信息,以及要接入到的指标数据仓库信息,咱们可在代码中 create 对应的 SQL,而后执行 insert 便能够实现整个接入。
一个从业务 MySQL 数据库接入数仓 Kafka 音讯队列的 demo 代码如下:
<img src=”https://img.alicdn.com/imgextra/i4/O1CN010g7tGi297fevcN2aT_!!6000000008021-2-tps-404-214.png” alt=”7″ style=”zoom:50%;” /><img src=”https://img.alicdn.com/imgextra/i3/O1CN017vJaaF23BtcJSVMTy_!!6000000007218-2-tps-456-212.png” alt=”7″ style=”zoom:50%;” />
2.2.2 数据 ETL
在数据实现接入后,咱们就能够开始业务逻辑,也就是用户总资产的计算了。
依据后面提到的计算公式,须要先对“账户持仓数据”和“股票报价数据”做一个关联,而后进行一次账户维度的聚合算出用户持仓市值,再和“账户现金数据”关联算出总资产,对应的 SQL 代码如下:
然而,在理论的运行中咱们发现,数据的输入后果仿佛很不稳固,变动频繁,输入的数据量很大,这里通过之前社区一些 Flink 的分享 [1] 发现,这类实时流数据的 regular join 可能会有数据量放大和不精确的问题,起因是因为 Flink 有时会把上游的一条数据拆成两条数据(一条回撤,一条新值),而后再发给上游。
那在到咱们总资产计算的这个场景中,能够看到在咱们的 SQL,的确在关联之前和关联之后都会往上游输入数据;另外,再做聚合 SUM 的时候,上游的一个变动也可能触发两个不同的 SUM 后果;这些计算两头后果,都在一直地往上游输入,导致上游的数据量和数据的稳定性呈现了肯定的问题,因而这里要对这些回撤进行一个定的优化。
依据之前一些社区的分享教训来看,这里对应的一个解决方案是开启 mini-batch;原理上应用 mini-batch 是为了实现一个攒批,在同一个批次中把雷同 KEY 的回撤数据做一个对消,从而缩小对上游的影响;所以这边里能够依照官网的文档做了对应的一个配置,那么数据量和稳定性的问题也就失去了初步的一个缓解。
2.2.3 提供数据
这部分的次要目标是将 ETL 计算好的后果进行保留,便于上游接口间接查问或者再做进一步的流计算应用,因而个别能够抉择存储到数据库和音讯队列中;
2.3 扩大数据利用
在实现根本数据模块的计算后,咱们能够从数据的价值角度登程并摸索更多可能,例如对曾经接入的数据,能够再做一个二次的数据开发或开掘,这样就可失去其它视角的数据,并进一步实现数据中台独特的价值。
以用户总资产为例,在咱们在计算出用户总资产这个数据之后,咱们能够再以此作为数据源,从而实现用户的实时总资产走势。
应用 Flink 自带的状态治理和算子的定时性能,咱们能够大抵按如下步骤进行实现:
- 接管上游不断更新的全量用户资产数据,并在 Flink 外部一直保护最新的用户资产截面
- 配置定时器,定期地扫描最新的用户资产截面,配上零碎设定的工夫戳,失去以后截面的资产快照数据
- 将以后截面的资产快照数据输入到上游的数据库或音讯队列中
2.4 数据稳定性的挑战
在我的项目实际上线过程中,咱们还遇到了一些引入流计算后带来的挑战,有时这些问题会对数据的准确性和稳定性造成肯定影响,其中首当其冲的是 DB 事务给 CDC 带来的困扰,尤其是业务 DB 的一个大事务,会在短时间内对表的数据带来比拟大的冲击。
如图,如果业务 DB 呈现了一个交易的大事务,会同时批改现金表和持仓表的数据,但上游处理过程是离开并且解耦的,而且各自解决的过程也不统一,就有可能呈现钱货数据变动不同步的状况,那么在此期间算出的总资产就是不精确的。
那么这里针对这种状况,咱们也有一些应答计划:首先一个计划和后面解决回撤流的思路相似,是通过窗口进行攒批次的一个解决,尤其是 session 窗口比拟适宜这个场景。
例如下图中的代码,在计算出用户资产之后不是立即输入后果,而是先做一个 session 窗口,把流之间最大可能提早的变动蕴含进去,即把 session 窗口外面最新的后果作为一个比较稳定的后果作为输入;当然这里的 gap 不能太长,太长的话窗口可能会始终无奈截断输入,须要依据理论状况抉择适合的 gap 大小。
另一个计划的话能够是对此类大事务做一个辨认,当上游触发一个很大的变动时,能够给 ETL 程序做一个揭示或预警感知,这样的话 ETL 程序就能够对输入数据做一个临时的屏蔽,等到数据稳固之后再复原输入。
再有的话就能够是晋升性能和算力,假如解决数据的机器性能越强,那在同样工夫数据被解决就越会更快,各流之间的提早就越小。
三、总结
在这个场景中,咱们通过引入 ETL 模式和 Flink 流计算引擎,实现了计算和存储的拆散,将计算的累赘从后端程序转移到了 Flink 流计算引擎上,不便的实现算力的动静扩缩容,还缩小了对业务数据库读取的压力。除此之外,流计算出的实时后果还能够进一步给上游(用户实时走势)应用,实现了更多的数据利用价值。
参考:
[1] FFA2021 核心技术的分享《Flink Join 算子优化》
扫码进入赛事官网理解更多信息:
更多内容
流动举荐
阿里云基于 Apache Flink 构建的企业级产品 - 实时计算 Flink 版现开启流动:
99 元试用 实时计算 Flink 版(包年包月、10CU)即有机会取得 Flink 独家定制卫衣;另包 3 个月及以上还有 85 折优惠!
理解流动详情:https://www.aliyun.com/product/bigdata/sc