中原银行 OLAP 架构实时化演进
![](https://img.haomeiwen.com/i17302790/8bc96c458c85a403.jpg)
摘要:本文整理自中原银行数据信息部杜威科,在 Flink Forward Asia 2022 行业案例专场的分享。本篇内容主要分为四个部分:
- OLAP 实时化建设背景
- OLAP 全链路实时化
- OLAP 实时化探索
- 未来探索方向
![](https://img.haomeiwen.com/i17302790/a800c2a3a7781ec9.jpg)
中原银行成立于 2014 年,是河南省唯一的省级法人银行,2017 年在香港联交所主板上市,2022 年 5 月经中国银保监会批准正式吸收合并洛阳银行、平顶山银行及焦作中旅银行。合并后总资产突破 1.2 万亿,在国内城市商业银行排名第八位,下辖 18 家分行、700 余家营业网点及 17 家附属机构,先后荣获“年度十佳城市商业银行”、“铁马十佳银行”、“最佳上市公司”等称号。
一、OLAP 实时化建设背景
![](https://img.haomeiwen.com/i17302790/6d89537254a52fe1.jpg)
近几年实时需求涌现,尤其是银行更加重视挖掘实时数据的使用与价值。主要表现在逐年增多的实时报表、实时大屏等面向 BI 的场景。还有实时指标或特征计算等面向 AI 的场景。从技术角度,实时 OLAP 相较于传统 OLAP 发展起步较晚,多种多样的实时数据需求对实时 OLAP 体系也提出了更高的要求。随着近年来技术迭代,如 StarRocks、ClickHouse 等支持实时 OLAP 场景的数据库也是推陈出新,对于解决银行业的实时场景也带来了更多可能。
![](https://img.haomeiwen.com/i17302790/e12b724570d70964.jpg)
银行业想要获取实时报表数据,这样基本的 OLAP 场景需要解决哪些困难呢?
首先需要全链路实时化。全链路是指数据实时采集、实时分析、实时写入数据库以及实时提供查询分析。整个链路的实时化相较于传统的 OLAP,各个环节均有一些难点需要克服。比如受到银行记账模型无法变更、数据库管理严格、数据安全要求较高等多方面的限制,当前金融行业数据实时采集也不是一路畅通的。另一方面来说,对于流计算业务,实时计算面临数据源多、整合困难、技术复杂、监控运维成本较高等问题。业务需求也往往涉及多个数据部门配合,多种业务类型交织,一旦流计算任务出现问题,监控分析排查也会比较困难。
其次,从生产实践得知,实时场景仅有实时数据往往是不够的,需要配合离线数据才能计算出所需的业务数据。尤其是在银行体系下,面向规范化、精准化加工的传统离线数仓体系,能够较好的解决财务分析等场景,且在很长时间内仍是主流方案。离线数据加工的复杂度往往也较高,当前阶段尚无法达到全部业务数据的实时化计算。
最后,普遍依赖维度表。众所周知,在 kimball 维度建模中,分为事实表和维度表。在我行,基于事实表的场景基本上已经解决。但银行业的报表大多都基于维度表的统计分析,该场景也是银行业实时报表落地困难的关键因素之一。
为了解决该场景,我行进行了大量的生产实践,但仍未有较好的解决落地方案。希望随着实时技术的发展能够彻底解决该场景。
二、OLAP 全链路实时化
![](https://img.haomeiwen.com/i17302790/414fa30cb342da00.jpg)
首先介绍一下实时化的演进历程,对整个发展过程和未来的方向有一个概括性的了解。
-
第一阶段:起步。基于 Kafka 的实时 ETL,包括实时采集、实时加工、实时载入、实时 OLAP。该架构能够解决的问题大都是基于事实表的统计分析,已经在行内有大量的落地案例,但无法解决银行基于维度表的统计分析。另外,该方案很难形成规模化的数据分层复用,Kafka 数据无法查询和长期持久化等问题也比较突出。
-
第二阶段:探索。为了解决银行业大量基于维度表统计分析场景,先载入后分析,也就是 ELT 的方式。过程是先实时采集,然后不进行逻辑加工直接实时载入,最后再实时 OLAP 查询阶段进行逻辑加工。
-
在 ELT 探索初期,我们采用过微批全量的方式,在数据实时写入到数据库后,定时执行全量加工逻辑,类似于离线数仓跑批的概念。只不过是从每天跑批缩短到了小时级别,甚至分钟级别,达到准时加工的效果。显而易见这种方式不可取,存在时效性差、跑批不稳定等问题。
-
随着 MPB 数据库的发展,查询性能也得到了极大的提升。使用 View 视图嵌套加工逻辑的方式也进行了探索,也就是把业务数据以 CDC 的方式载入 MPP 数据库的明细层,分析查询逻辑使用 View 封装,在查询时触发底层计算。这种方式也可以解决维度表的统计分析,但每次查询资源消耗太大,无法大范围推广。这种 ELT 方式虽然能够解决一部分的实时场景,但局限很大。
-
-
第三阶段:优化。接下来到了优化升级和未来方向选择的节点。为了解决银行业基于维度表的实时 OLAP,必须把部分计算向前移动到 Flink 计算。数据湖 Flink Table Store(Apache Paimon) 的出现,使基于维度表的全量统计分析成为了可能。也就是前期一部分的加工工作在 Flink 中完成,另一部分聚合等计算工作在 OLAP 数据库中完成,两者分摊了计算的时间消耗。
-
第四阶段:未来。在未来还是希望能够把全部加工逻辑在 Flink 端完成,向着存算分离流批一体的流式数仓方向发展。
![](https://img.haomeiwen.com/i17302790/ef0a02f85150690a.jpg)
全链路实时化具体是怎么做的呢?承载哪些业务或者使用了哪些组件呢?上图我们从下往上看。最下面是数据源,分为了四类实时数据,分别是业务的数据库数据、客户的行为埋点数据、网络流量日志类数据、应用消息直接产生的数据。所有数据均打入 Kafka,供后续的实时计算平台使用。
中间是实时计算平台,加工逻辑使用 Flink SQL 和自定义函数处理,Flink 任务运行在 Yarn 或 K8s 上,当前主要推广运行在云环境上。使用 Kafka 和 Flink Table Store(Apache Paimon) 作为数据的传输和存储,维表统一使用 ES 提供。在银行业维表使用比较普遍,同一张维度表可能使用其中的多列进行关联,且维度表往往需要实时的,如在新开户场景。在我们平台上,使用频率较高的维表,引用次数达 60 多次。
再往上来到了数据服务层,提供在线服务的同时需要支持实时数据的写入,常用场景是直接写入业务目标数据库 Oracle 或 MySQL 提供在线服务。大多数场景数据是写入公共的 ES 或者 StarRocks,提供查询或者在线分析服务,后期也会提供直接对 Flink Table Store(Apache Paimon) 的查询。
最上层是各个业务场景的实时数据需求,如实时反欺诈、实时营销、数据安全行为分析、实时报表等场景。
![](https://img.haomeiwen.com/i17302790/5597c55d475db8b5.jpg)
左边的数据源有关系型数据库 Oracle、MySQL,还有在起步阶段的国产 OceanBase。银行当前主要使用的还是 Oracle,我们采用商业的实时数据采集工具 Attunity Replicate,该工具在部署方式、抽取数据的时延和吞吐表现优秀。对少数 MySQL 采用了开源的 Flink CDC 工具,该工具满足各个场景的需求。明年行内将大范围推广国产的 OceanBase 数据库,其自带的 OMS 数据迁移工具是抽取该库的最好选择。
这几种关系数据库均采用 JOSN 格式,全部写入 Kafka 中。对于手机银行、微信银行等用户行为埋点数据,使用的是商业神策平台提供的能力。实时计算平台直接从神策的 Kafka 进行数据消费。交换机的流量镜像等日志经过报文解析后也直接写入 Kafka,这部分的实时流量是最大的。另外还有少量产品是把相关的实时数据直接写入 Kafka。
对于 Kafka 中的 topic,也有多种方式适配不同的数据场景。对于关系型数据库,一张表对应一个 topic。对于用户行为,采用大宽表的形式把所有数据都写入同一个 topic。采用 Kafka 作为统一对接下游流计算平台,达到复用 topic 的目的,如核心的交易流水表复用了三十多次。
通过介绍发现不同场景的实时数据最优的采集工具也不同,通过各种采集工具抽取了各个业务部门的数据,但海纳百川,都需要流入 Kafka 对接后续的实时计算。
最后抛出来一个疑问,对于纷繁复杂的数据源,大家是如何统一管理起来的呢?
![](https://img.haomeiwen.com/i17302790/bb04003114ee7201.jpg)
2018 年首次引入实时计算业务,主要以代码开发为主。2019 年开始系统的建设实时计算平台,以 Flink SQL 开发实时业务,能够界面配置、启停、监控任务。2020 年支持运行在 K8s 云平台上,能够手机小程序远程监控,承载的任务也达到了 100 多个。2021 年开始支持 CDC 同步场景,探索实时 OLAP,承载的业务也达到了 200 多个。2022 年支持了最新的 Flink Table Store(Apache Paimon) 湖存储,也引入了高性能的 OLAP 引擎 StarRocks,探索实时报表场景,承载的业务也达到了 300 多个。
![](https://img.haomeiwen.com/i17302790/4f7965ca8da38c2a.jpg)
这几年实时任务的运行现状如下:
实时任务个数 380+,以每年 100+的速度稳步增长。支撑了二十多个项目组的业务需求。日均处理数据行数 50 亿+,日均接收数据量 20T+。
这么多的实时任务多种多样,如流量日志计算指标,数据量大但逻辑简单;监控用户账户信息,数据量小但引用维表个数较多;监控用户行为埋点数据,使用了 CEP 进行复杂事件处理。
![](https://img.haomeiwen.com/i17302790/75f9dcbe28179788.jpg)
显然数据加工实时化在链路中处于关键位置,平台化也能够降低使用门槛,加快开发效率。用户能够像使用普通的 SQL 一样,对实时的数据进行处理,不需要关注流计算底层复杂的处理过程,极大地降低了实时数据开发的门槛。
其中主要的功能有数据源管理、实时任务开发、任务运维监控、项目管理、集群管理等功能。在实时任务开发模块中,主要有数据源配置、源表/维表/结果表配置、SQL 开发、自定义函数、SQL 语法检测,包括上线过程中需要的导出和导入功能。
在任务运维中有收发统计、集群资源监控、异常短信告警、远程小程序监控等,同时具备企业级的权限管理、租户管理等功能。该平台涵盖了实时数据开发的全生命周期,平台化可以彻底规避繁重的底层流计算处理逻辑,繁琐的提交过程等。为用户打造一个只需要关注实时计算逻辑的平台,助力企业向实时化、智能化大数据转型。
![](https://img.haomeiwen.com/i17302790/06934ebcb06d78bd.jpg)
前面也已经提到了,实时计算的场景往往离不开离线数据,不管是在数据加工阶段,还是在查询分析阶段,实时数据主要是写入 Oracle、MySQL、ES、StarRocks 等。
以 StarRocks 为例,写入的既有离线数据,也有实时数据。既有写入 ODS 层明细层数据,也有计算汇总后的 ADS 层汇总数据。StarRocks 作为一款 MPP 架构的高性能数据库,能够支撑 PB 级的数据量,拥有灵活的建模方式,可以通过向量化引擎、物化视图、位图索引、稀疏索引等手段构建统一的数据存储系统。
我行搭建了一站式商业智能 BI 平台,该平台有客户行为分析系统——知秋、一站式报表平台——鲁班、一站式大屏——鸿图、自助分析平台——云间、一站式活动运营平台——智赢等系统,未来还会加大对Table Store的投入,作为实时数据的统一存储。
![](https://img.haomeiwen.com/i17302790/f01f4ac9512b981c.jpg)
接下来我们看一下典型 ELT 链路的工作过程。当前银行业的数据库主要还是 Oracle,采用商业的 Attunity Replicate 实时采集数据。该工具提供全量和增量的实时同步,秒级时延,数据以 JOSN 格式统一写入 Kafka,以便复用 topic。也可以按照主键哈希顺序写入 topic,以保证分区有序性。
然后基于 Flink SQL 构建的实时计算平台进行业务逻辑处理,统一使用 ES 作为维表,关联离线和实时的数据。这里没有选择 Hbase 和 Redis 作为维表是因为他们只能主建关联,构建二级索引又比较麻烦。另一方面,维表数据量最大也就是千万级别,使用 ES 能够满足所有场景。
最后数据实时写入 StarRocks 中,StarRocks 支持快速 update,提供高效 OLAP 的能力,能够应对多种查询场景。这个典型的 ETL 链路对于事实表的行为分析有很好的效果,比如用来统计交易笔数、交易金额、业务量等指标,但对于维度表的分析却无能为力,比如计算分支行存款余额场景。
三、OLAP 实时化探索
![](https://img.haomeiwen.com/i17302790/829d574edde50632.jpg)
我们以银行的典型动账场景为例,一次动账操作其实是一个事务,至少要操作两张表。第一张表是交易流水表,记录转账的一次行为,第二张则是用户的属性表,其中有一个字段是用户的余额,需要随着转账同步更新。
上图中的两个表是演示两次转账动作,该场景在 12:00:01 秒张三转入 100 元,客户表张三的余额也从 100 更新为 200。12:00:02 秒,李四转出来 100 元,客户表李四的余额也从 200 元更新为 100 元,在这个转账场景下进行分析。
流水表的特点,主要是 insert 操作,记录行为信息,适合增量计算,如统计开户、取款、贷款、购买理财等行为事件。刚才提到的典型的基于 Kafka 的实时计算能够较好的解决该场景,比如实时营销包括大额动账提醒、工资代发、理财产品购买、申请反欺诈、交易反欺诈等。在贷后管理也有应用,如零贷贷后临期催收、扣款等。
客户属性表的特点,主要是 update 操作,记录属性信息,客户的总资产、贷款、理财、基金、保险等产品的余额是在维度表中,所以常使用维度表全量计算资产信息,如资产余额类的计算等。
应用的场景主要是实时报表和实时大屏,比如对公 CRM、零售 CRM;经营管理;资产负债管理等。
![](https://img.haomeiwen.com/i17302790/4b26280f3de10f5e.jpg)
接下来主要探讨的是基于维度表的实时全量计算场景。以在行内落地的对公 CRM 实时存贷款场景为例,来讲解一下涉及哪些方面的工作。对公 CRM 实时存贷款功能面向总分行领导、支行行长、客户经理等,可以随时查看行内分支行及客户的存贷款情况,从而时刻掌握全行的资产最新状况。
从数据的角度来看,分为三个部分,实时数据、离线数据、实时查询分析数据,也就是在查询的时候才开始进行逻辑计算。
先来看一下实时数据,不断变化的有存款余额、贷款余额、应解汇款、实时汇率、新开账户等。刚才提到实时场景往往离不开离线数据一起进行配合计算,离线数据主要包括员工信息、机构层级、归属关系等基本信息,还有离线跑批生成的年末月末余额、绩效关系、管户关系等。
这两部分数据均载入到实时 OLAP 引擎,用户查询的时候在引擎内计算资产负债明细汇总,根据绩效关系对资产负债进行分组聚合。实时的存贷款和日终、月终进行比较,分支行根据存贷款进行排序等。对公 CRM 提供的查询功能有全行汇总、分支行汇总、分支行明细、分支行下转、客户明细、年末月末比较、趋势分析等。
![](https://img.haomeiwen.com/i17302790/d8f6a50d4a7269cb.jpg)
了解了实时存贷款业务功能,下面我们来看一下是如何实现的。上图是该案例的技术架构图,也就是使用了实时的 ELT。
首先,实时数据全部来自于 Oracle 数据库,通过实时采集导入到 Kafka。使用流计算平台,以 CDC 的形式写入到 StarRocks,在其中构建全量和增量的数据。作为 ODS 原始层,离线数据在数仓中跑批生成,使用离线同步工具,百川平台以 T+1 的形式写入 StarRocks,然后在 StarRocks 中使用 view 灵活的对数据进行转换处理。View 视图可以随业务进行调整,上层应用直接查询封装好的视图实现即席查询。当用户进行点击的时候,触发原始的数据进行计算,如查询某分行的存款余额。
该方案可以解决基于维表的实时全量计算场景,无需跑批,现场计算,端到端分钟级甚至秒级完成。尤其是在月末、季末等关键节点,给分支行的领导查询最新资产负债等信息带来了极大的便利。
当然,该方案并不完美,缺点是当 view 的逻辑较为复杂,数据量较多时,查询性能影响较大,因此比较适合数据量不大、对 QPS 要求不高、灵活性要求较高的场景,且需要计算资源比较充足。
该方案的探索也让我们得出了一个宝贵的经验。虽然 OLAP 引擎性能强大,但仍然不能把所有的计算逻辑全部在引擎中执行,必须向前推移。但是 Flink 只有计算没有存储,这个问题该怎么解决呢?具体有哪些方面的困难呢?下面来分析一下。
![](https://img.haomeiwen.com/i17302790/4bf10d6ed2d88d9a.jpg)
想要解决基于维度表的实时全量计算,存储需要以下三个能力。
-
第一、存储全量数据,并支持快速更新。维度表有大量的更新操作,比如在结息日源库进行跑批的时候。
-
第二、支持流批写、流批读,尤其是流读。流读是数据驱动计算分析,只有能够流读才能使用数据自动计算分析,而不是使用微批调度或者查询时触发分析计算。
-
第三、支持存储“完整”的 changelog。完整的数据库日志存储是数据驱动计算正确性的重要保证。
四、未来探索方向
![](https://img.haomeiwen.com/i17302790/e93a3b64ed46a6dc.jpg)
今年发布的 Flink Table Store(Apache Paimon) 能够很好的解决之前遇到的问题。Flink Table Store(Apache Paimon) 是一个统一的存储,用于在 Flink 中构建流式处理和批处理的动态表,支持高速数据摄取和快速查询,是一种湖存储格式,存储和计算分离。导入数据时双写到数据文件和日志系统,并且支持流批写入、流批读取,支持快速 update 操作。还支持丰富的 OLAP 引擎生态,比如 Hive 等。我还了解到 StarRocks 也在支持数据湖查询,相信在不久的将来 StarRocks 也能够支持查询 Flink Table Store(Apache Paimon)。
![](https://img.haomeiwen.com/i17302790/2924e8d85c98f6f2.jpg)
在加入 Flink Table Store(Apache Paimon) 后,原有的 ELT 架构的基础上进行优化升级,带来了如下变化。
在流计算平台中,把原始数据写入 Flink Table Store(Apache Paimon),实时存储历史全量和实时更新的表数据,然后计算逻辑使用 Flink SQL 实现,最后把初步汇总的数据写入 StarRocks 中,原始明细数据在 Flink 中计算,极大减少了 StarRocks 的计算量。
![](https://img.haomeiwen.com/i17302790/ef08e28c016f1a9a.jpg)
这种架构我们在生产上已经进行了初步尝试,效果非常显著。但这并不是终点,上图展示的就是未来的蓝图,我们将朝着流式数仓的方向进行演进。流式数仓能够支持存储全量的数据和完整的 changelog,也支持批量导入离线数据。使用廉价的存储和存算分离,能够更加灵活的进行弹性计算。
数仓的分层可以解决实时数据的复用,多指标随着数据的实时流动而实时变化,数据主动的变化驱动分析,从另一个角度说也是在使用空间换取时间。当数据在源头发生变化时就能够即刻捕捉到,让所有数据实时的流动起来,并且对所有流动中的数据都可以进行实时或批量的查询。
离线数据和实时数据共同存储在 Flink Table Store(Apache Paimon) 中,离线分析 SQL 和实时 SQL 完全一样,最终达到流批一体的效果。那么为什么现在不直接采用这种架构进行构建呢?当前阶段这个架构还无法落地,比如其中聚合计算有大量的撤销动作,多个层次间的实时数据流动也需要大量的资源和调试技能,不过我相信流式数仓一定会到来。