摘要:本文整理自微财资深数据开发工程师穆建魁老师在 Flink Forward Asia 2024 行业解决方案(一)专场中的分享。主要分为以下三个部分:
一、微财科技基于 Flink 构建时变量池分享
二、选择 Flink 进行流式计算的架构选型和开发效率提升策略
三、实时变量池架构与多流关联优化实践
一、微财科技基于 Flink 构建时变量池分享
本次分享的的主题是微财基于 Flink 构造实时变量池。首先,我简单的介绍一下我们的公司。微财科技是一家专注于互联网金融的公司,其核心业务是通过 APP为用户提供借款服务。当用户下载登录 APP 后申请借款时,系统会根据一套复杂的风险评估机制来决定是否批准该申请。这套风险评估机制主要依赖于两个关键组成部分:模型与策略。其中,变量作为这些模型和策略的重要输入数据,对于确保风险评估的准确性至关重要,从而直接影响到用户的借款申请能否获得批准。
什么是变量呢?简而言之,变量就是描述用户行为或属性的数据。例如,用户的年龄、性别以及收入水平等。在变量的众多分类中,有一类被称为实时变量,它指的是通过实时数据计算得出的变量。
为什么需要实时变量呢?或者在哪些场景下会需要实时变量呢?这里将通过公司两个简单的场景来为大家举例说明。首先,考虑一个 T0 的新用户,即一个在当天注册并完成进件流程的用户,他此时没有历史数据可供参考。因此,当这位用户发起借款请求时,我们需要对其进行风险评估,而这时只能依赖他的实时数据来进行评估。
在另外一个场景下,即老用户的 T0 变异情况。如果仅依赖用户 T-1的数据来对其进行风险评估,那么评估结果很可能是错误的,或者会导致误放的情况。在这种场景下,这样的评估结果对公司来说是无法接受的。因为这样的错误评估将直接导致公司的现金损失。
如何产出实时变量呢?或公司原先的计算方案,以及业内普遍采用的解决方案是什么?答案是通过即时计算,即请求来一条处理一条。每当有用户需要进行风险评估时,我们就会从数据库中提取与其相关的数据。获取到这些数据后,在代码层面进行加工和计算,最终将计算出的变量提供给风险评估系统,以便其进行风险评估。
这个方案存在以下几个痛点。首先,其 QPS 上限不高。随着用户量和业务量的增长, QPS 的压力会反向传导至前端的数据库组件,如 MySQL 和 MongoDB 。为了加速查询,就只能在原有的数据库组件上添加索引,而且这些索引只能添加在存库上,因为在主库上添加会影响线上业务的正常运行。然而,添加索引并非短时间内可以完成的任务。此外当存库发生故障需要新建时,代价非常高昂,会直接影响线上服务的SLA。在这种场景下,实时变量计算与数据库组件的耦合度非常高。
为了解决上述痛点,将决定采用 Flink 流式计算方案。在数据同步阶段,首先利用 Flink CDC 将数据采集到 ODS 层。随后,通过流式数据驱动下游的 Flink 任务来生成变量,并将这些最终变量写入一个 OLAP 引擎中。这样一来, QPS 的压力就主要集中在 OLAP 引擎上了。同时,由于采用了 Flink CDC 进行数据同步,因此不再依赖于原有的数据库索引。值得一提的是,自今年年初完成上云后, CDC 已经支持 GTID 同步。一旦数据库发生故障,便可以在云端迅速启动一个新实例,并从之前的 binlog 同步位置继续数据同步。这样我们就能完成和业务组件的解耦,显著提升整体变量 SLA 的稳定性。
二、选择 Flink 进行流式计算的架构选型和开发效率提升策略
在选定 Flink 作为公司的流式计算引擎之后,面临的首要问题是架构选型,这是一个需要仔细考量并编制具体场景的问题。 Lambda 和 Kappa 这两种架构各有其独特的优势和适用场景。当时选择 Kappa 架构而没有选择 Lambda 架构的关键原因在于, Lambda 架构本质上仍是一个离线加实时的解决方案。由于变量要求具有高度的准确性,即需要达到百分百精确一致,而 Lambda 架构无法有效解决这个问题。此外,如果采用 Lambda 架构,对于同一个变量,需要同时开发离线和实时两套系统,这无疑会降低开发效率。相比之下, Kappa 只需开发一套计算逻辑,因此相较于 Lambda 架构开发效率会有所提升。并且,随着 Flink 的快速迭代,可以利用 Flink 的 Exactly-Once 语义来严格保证变量的一致性。
在选择 Kappa 之后,又遇到了新的挑战,即开发效率的问题。这里所说的开发效率慢,并非指 Flink 本身运行缓慢,而是指相较于之前的批处理计算方式,采用 Kappa 架构后,开发流程受到了较大的影响。有人可能会说 Flink 的性能并不差,但问题在于 Flink 无法满足当前业务的特定需求。主要问题包括:一是快速迭代的风险变量更新过程中,使用Flink SQL无法有效从现有状态恢复;二是处理长时间跨度(如半年到一年)的用户行为数据时,多流关联操作容易导致状态膨胀。此外,虽然转向DataStream API可以解决部分问题,但这也增加了学习成本,尤其是对于习惯于Java开发的团队来说,需要额外掌握Flink的各种算子及其状态管理机制。该如何解决这个问题呢?是否存在一种方案,既能利用 Flink SQL 的快速开发能力,又能避免直接操作细粒度 state 所带来的问题呢?
解决方案是实施数据分层,因为数据分层对于数据开发人员来说通常比较熟悉。在变量计算层面,主要分为两层:变量原子层和完整变量计算层。在变量原子层,完全采用 DataStream API 的方式对数据进行清洗、加工,以及多流关联和数据打宽等操作。同时,针对不同的数据源严格控制其生命周期,以避免state 无限制地膨胀。在加工完变量原子层后,在上层进行变量计算时,便可以专注于变量的加工逻辑本身。这意味着即使需求快速迭代,也能利用 Flink SQL 快速完成变量的加工,迅速适应需求的变化。采用这种变量分层策略后,开发效率相较于以前的即使变量计算,我们的整体开发效率大约提升了 30% 。
三、实时变量池架构与多流关联优化实践
在提到使用 DataStream API 构建原子层时也涉及了多流关联的问题。这确实是实时开发中一个难以避免的挑战。多流关联的主要难题在于, Flink 仅提供了 connect API ,若要进行多流关联,可能会导致状态冗余。此外,使用 connect API 会使代码变得复杂且冗余,增加了维护难度。在优化多流关联的场景中经历了长时间的探索,并尝试了许多方法。最终通过使用 Union 加 keyBy 的方式,将多个流合并后,再进行状态管理,从而解决了大状态的问题。同时,由于我们在原子变量层严格控制了不同数据源的生命周期,帮助我们避免了大状态问题的出现。
这就是完整的变量池架构,在实时变量池完成变量的加工后,所有的变量都被存储到了 Doris 中。而选择 Doris 的原因在于,一些变量场景需要进行观察点的计算,比如计算用户从注册至今的天数。因此,在选择 OLAP 引擎时,除了要考虑其高并发点查能力外,还希望该引擎具备一定的 SQL 查询能力。为此在 OLAP 引擎外部还封装了一层查询接口,用于处理线上的实时查询请求,并将这些实时查询日志记录到Paimon中。
由于我们公司本身就是一家互联网金融公司,因此对数据的时效性和线上数据的质量要求都非常严格。在将线上查询日志记录到Paimon之后,通过离线任务设置了按小时级的定时调度。这一调度主要对线上变量调用的结果进行实时的质量监控。这里主要关注四个重要指标: PSI 、缺失率、均值以及方差。针对每个变量都设定了相应的告警阈值。一旦触发告警就能实时地通知相关人员。以下图表展示了我们线上的实时质量监控结果。
在这套实时变量架构落地之后,今年除了风险场景外,已经成功将应用场景极大地扩展到了公司的其他业务领域。目前,营销市场、客服部门,甚至财务部门都在使用这套实时变量来辅助业务决策。
在未来展望方面,目前使用的是自建的 Doris 作为线上的 OLAP 引擎。同时,我们也在积极接触阿里云上的云原生产品,如 StarRocks 和 SelectDB 。目前正在对这两个产品进行深度的测试,并期望将来 StarRocks 或 SelectDB 能够替代自建的 Doris ,以确保线上服务的稳定性。
更多内容
活动推荐
阿里云基于 Apache Flink 构建的企业级产品-实时计算 Flink 版现开启活动:
新用户复制点击下方链接或者扫描二维码即可0元免费试用 Flink + Paimon
实时计算 Flink 版(3000CU*小时,3 个月内)
了解活动详情:https://free.aliyun.com/?utm_content=g_1000395379&productCode=sc