中泰证券股份有限公司成立于 2001 年 5 月,是全国大型综合类上市券商,在全国 28 个省市自治区设有 45 家分公司、300 多家证券营业部,员工 9000 多人,形成了集证券、期货、基金等为一体的综合性证券控股集团。
目前中泰证券服务客户超 770 万,为企业融资近 1.5 万亿元,公司管理总资产额超过万亿,在全国各地拥有 300 多家营业部为客户提供各种服务。可以说中泰证券在证券行业拥有着很强的综合实力。
01
平台发展历程
随着业务的不断发展,对数据的时效性要求也越来越高,传统的离线计算越发步履艰难,业务驱动着我们建立一套实时计算平台和体系。在实时计算平台的探索过程中,性能、场景的支持度、稳定性一直是推动我们平台不断升级的原动力。
首先在性能方面,需要一款高性能计算引擎支撑公司的实时类业务;其次在应用场景方面,需要平台快速响应业务需求,上线各类服务;最后在稳定性方面,证券行业的特点决定了实时计算平台需要拥有很好的容错性和高可用性。
基于上述建设背景,我们平台一共经历了四次技术变迁。
1. 第一阶段,在 2018 年初,基于 Storm 计算引擎构建第一版实时计算平台,采用的是一种组合式的编程模式。
2. 第二阶段,在 2021 年 2 月,我们基于 Flink 构建了第二版实时计算平台,采用了声明式的编程模式,并上线了第一个 Flink 业务应用。
3. 第三阶段,在 2022 年 7 月,借助云原生的发展,推动了 Flink 与 K8s 的集成。基于 Pod 进行 Task 资源调度,并进行大规模的业务推广。
4. 第四个阶段,从 2022 年至今,平台一直在探索流批一体的整体解决方案,寻求新的数据处理架构。
第一版实时计算平台基于 Storm 计算引擎构建,采用 Storm 原生的 API,Spout、Bolt 构建任务拓扑,窗口计算、状态存储等功能特性通过引入第三方组件实现。在资源调度上,采用 Storm Standalone 模式部署,所有的任务共享集群的资源。此时的实时计算平台在客户关键时刻提醒 MOT、合规风控等场景开始应用起来。
然而平台运行不久,Storm 计算引擎开始暴露出一些问题。
1. Storm 计算框架自身支持的能力不足,像 Exactly Once、窗口计算、状态存储等特性均不支持,难以应对复杂的计算场景。
2. 开发成本太高,上线周期太长。Storm 基于组合式的开发方式,任务的拓扑关系、数据的分发方式都需要开发者自行指定,本身就存在一定的开发门槛,简单的作业也需要开发者编写大量的冗余代码。
3. 资源隔离粒度较差,作业运行相互影响。另外,Storm 部署架构中 Nimbus 节点负责任务的调度,资源数据的收集、分发、Jar 包等功能。当集群作业增长到一定数量级时,Nimbus 节点将变成整个集群的性能瓶颈。
针对 Storm 计算引擎的种种问题,我们来看一下 Flink 计算引擎是如何一一解决的。
首先在功能特性的支持上,Flink 借鉴了一篇关于分布式快照的论文,实现了只处理一次语义,同时提供了多种状态存储方式等等。正是这些特性的引入,为实时计算的复杂场景提供了很好的技术支撑。
其次在开发方式上,Flink 提供了 Flink SQL、Table API、Data Stream、Stream Processing 四个级别的抽象,为程序开发带来了很大的灵活性,开发者可以针对不同的业务场景灵活选择。
最后是资源调度上,Flink 支持 Yarn、K8s 等多种调度方式,可以对资源进行更细粒度的控制,使资源的利用率更高,作业的隔离性更好。
因此以 Flink 计算引擎为核心的实时计算平台上线伊始,就为各业务提供了重要的支撑。截止到目前为止,实时计算平台已经囊括的数据源包括集中交易柜台、融资融券柜台、产品中心、资讯中心、公募基金、账户系统、综合金融、资金管理等众多核心的业务系统,同时为齐富通 APP、掌 E 通等多种终端提供服务。
02
架构&选型
上图是我们实时计算平台的整体架构图,从下之上主要包括数据源、数据的接入层、资源的调度层、实时计算平台、数据存储层以及数据应用层。
在数据源,主要采集业务数据库的变更日志、APP 埋点数据、日志数据、监控数据等等。数据接入层分为两种类型:
1. 对于结构化数据,平台使用商业产品 HVR 和 Flink CDC 进行采集。
2. 对于非结构化数据,平台使用 Elastic Beats 进行数据收集。
在资源调度层面,平台支持基于 Yarn、K8s 的资源调度,开发者可以灵活选择需要的资源调度方式。
实时计算平台支持多种开发方式,支持丰富的自定义组件,同时拥有全面的运维管理体系。经过实时计算平台加工后的数据,按场景进行分类存储,支持输出到 Kafka 消息中间件、HDFS 离线数仓、TiDB、MySQL 等关系型数据库,和 ES 全文检索引擎。
最后,数据应用层支持多种数据服务方式,可以通过服务订阅将数据推送到下游业务系统;通过接口平台将数据提供给其他系统使用。
基于实时计算平台的整体架构图,我们对实时计算平台的能力域进行了汇总,主要包括以下四个部分。
1. 开发方式。支持 Flink SQL、Table API、Data Stream API,以及正在调研使用的可视化构建等多种开发方式,支持不同类型的开发需求。
2. 资源调度上。开发者可以灵活选择 K8s、Yarn、Standalone 多种调度方式。
3. 自定义插件。为了提升开发效率,降低开发成本,平台针对具体的业务场景,抽象出类似数据清洗、数据去重、维表关联等开发模型。
4. 运维管理。稳定性、安全性一直是平台重点关注的内容,权限控制、监控、告警、日志收集、安全认证等功能支撑平台稳定安全的运行。
实时计算平台经过长期的技术积累、业务沉淀,可以总结出以下四大特性。
1. 敏捷的平台。支持与 DevOps 协同,一键部署线上作业。
2. 云化的平台。支持 K8s 资源调度,借助其强大的能力,实现资源的弹性扩缩容。
3. 安全的平台。采用多租户隔离机制,在数据存储、计算、调度等层面保障用户数据安全。
4. 开放的平台。拥抱开放的生态,开放的架构。
03
典型应用场景
实时计算平台的应用场景非常多,本次的分享主要从提升服务效能、实时数据管道、实时风险监测三个应用场景进行展开。
在实时平台上线之前,客户服务的时效性不足,这里列举了三个案例。
使用实时计算平台前:
1. 新股中签消息 T+1 天后,才告知客户中签。
2. 客户交易后缺少相应的信息反馈。
3. 客户不能及时获知自己持仓证券的风险警示信息,导致客户的体验感较差。
经过实时计算平台的业务场景改造后:
1. 客户可以第一时间获知中签信息。
2. 客户在交易后可以立即收到信息反馈。
3. 客户可以实时接收到证券的风险警示信息。
上图是提升服务效能应用场景的数据流图。
数据源主要来自上游的业务数据库,包括集中交易柜台、融资融券柜台、产品中心、资讯数据等等。通过 HVR 将数据库变更日志抽取到 Kafka 中,然后 Flink 进行数据消费、逻辑加工、维表关联,将最终的加工结果输出到 Kafka、TiDB、MySQL 等。
下游通过 MOT、KPM、综合金融等平台将数据发送到客户终端,以齐富通 APP、短信、微信为载体,将信息实时展示给客户。
上图向大家展示了提升服务效能场景改造后的建设成果。
第一张图展示了客户基金定投扣款失败的提醒,在扣款失败时及时告知客户失败的原因。后面两张图分别展示了客户新股中签的消息提醒和客户股票的成交提醒。
实时数据管道场景主要以技术角度为出发点,有以下四种数据流向。
1. Kafka 数据通过 Flink SQL 同步到 Kafka,实现不同 Kafka 集群间的消息复制,实现集群读写分离的场景。
2. 通过 Flink SQL 将日志数据落地到 HDFS,提供给后续审计、数据挖掘等场景使用。
3. 将监控数据实时写入 TiDB,实现监控运维大屏。
4. 将客户的流水数据、交易数据写入 Hbase,满足客户实时流水数据的查询。
上图是实时数据管道应用场景的数据流图。数据源仍然来自上游业务数据库,主要包括集中交易柜台、融资融券柜台、产品中心、平台的日志数据、用户行为数据等等。通过 HVR、Agent 将数据库的变更日志、行为数据等抽取到 Kafka 中,使用 Flink SQL 进行数据消费、逻辑加工、数据落地。最终提供给运营分析、运维管理、大屏展示等场景进行使用。
上图向大家展示了实时数据管道场景改造后的建设成果。
通过 Flink SQL 实现了运维监控大屏,可以通过运维监控大屏排查平台的 CPU、内存、网络 IO 等异常状况。
金融业是使用数据的重点行业,对数据具有高度的依赖性,出现数据安全问题的风险性也更大。公司一直倡导“合规风控至上”的经营理念,把风险管理文化建设作为公司发展战略的重要组成部分。实时计算平台为高效的风险监测带来了一种新的可能,主要涉及的风险监测场景包括实时维保比例监控、大额申报监控、频繁高买高卖监控、涨停价、跌停价申报监控等等。
目前风险监测主要存在以下几个痛点:
1. 在数据的时效性上,监测频率为分钟级别,数据的时效性严重不足,难以满足业务需求和监管部门的要求。
2. 在数据处理架构上,风险监测大多采用批量计算的模式,通过周期性调度作业的方式实现,存在丢失重要事件的可能性。
3. 在数据存储上,风险监测中间结果数据并不落地,导致无法查询历史的时点值,无法进行重要事件回溯。
上图是实时风险监测应用场景的数据流图。数据源主要来自上游的业务数据库,包括客户的股份数据、负债数据、委托数据、交易数据、行情数据等等。通过 HVR、Agent 将数据库变更日志、行情数据等抽取到 Kafka 中,实时计算平台进行事件消费,将客户交易数据与行情数据进行多流合并,并关联证券客户、信息等维表。
在数据架构上,采用原始层、明细层、汇总层三层架构,对数据进行组织。加工后的数据存储到 HTAP 类型的数据库,这里我们选择了 TiDB。同时在特殊场景下输出到 Redis 队列中,供下游系统进行消费。数据落地后通过数据推送、API 服务、报表系统等方式提供使用。
上图是以客户实时维保比例监测为例,展示的实时风险监测场景的建设成果。
维保比例 140%是警戒线,130%是平仓线。报表平台对维保比例跌破 130%平仓线的客户进行了筛查,并进行后续的业务处理。同时,无论是行情变动还是客户发生了交易行为,平台都将相应的记录落地,实现对历史任意时点值的维持担保比例查询,并提供可视化的方式展现其变化趋势。
接下来为大家分享实时风险监测在实施过程中的难点。
1. 在性能的方面,由于实时风险监测涉及到客户的股票、债券、基金等多种标的的综合计算,导致计算量比较大,计算逻辑复杂。虽然 Flink 支持通过横向扩展的方式解决性能问题,但对于当前的应用场景,从客户维度无法对任务继续进行拆解,横向扩展已经无法解决此类场景的问题。
2. 在数据准确性方面,对于任务运行过程中出现的一些异常情况,比如机器宕机、服务中断等等,如何保证数据的精准无误呢?
3. 在数据存储上,需要寻找一款兼具 OLTP、OLAP 场景的数据库,一方面 Flink 写入结果数据的 TPS 较高,另一方面需要对落地的数据进行统计、聚合分析。
针对以上三个难点我们的解决方案如下:
针对性能瓶颈方面的难点。首先需要找到作业性能的瓶颈点,我们通过 Task Manager 节点的 CPU 负载、Flink 的背压状态来定位具体的 Stream Operator。通过 Arthas 评估该 Stream Operator 关键路径的耗时,最终定位到产生性能瓶颈的具体业务逻辑。
在定位到性能瓶颈点之后,利用 Flink State 存储一些中间状态,避免业务逻辑重复计算。经过改造后,关键路径的耗时下降了一个数量级,优化的效果比较明显。最后在数据输出方面,合理设置 TiDB 的写入参数,最大程度的提升写入效率。
针对数据准确性保证方面的难点,我们做了以下尝试。
1. Checkpoint 指定持久化的存储方式,我们选择了星环 HDFS 作为存储底座,保证了任务在发生异常后可以恢复运行。
2. 作业上线后会根据业务的需求随时更新代码,我们需要设置 RETAIN_ON_CANCELLATION 参数,在任务版本的升级后,仍然可以恢复当前的状态继续运行。
3. 当上游系统出现异常时,操作 HVR 进行数据回放,保证数据源的可回溯性。同时 Flink 作业按照事件的类型进行幂等处理,保证整体数据的准确性。最后通过 Queryable State 查询作业运行过程中的状态数据,在线排查客户数据的异常问题。
针对数据落地方面的难点,TiDB 输出表开启 TiFlash 功能,TiDB 通过 raft 协议异步复制数据到 TiFlash。对于不同的查询场景选择不同的存储引擎,对于单客户的点查场景,通过 SQL Hint 指示使用 TiKV 存储引擎。对于聚合统计类的场景,比如我们要查询 Top 100 的客户,通过 SQL Hint 指示使用 TiFlash 列式存储引擎。经过实际观测,在此应用场景下,通过 TiFlash 引擎可以将查询的耗时由分钟级降低至秒级。
04
未来展望
未来我们将从以下三个方向进行探索:
首先,实时数仓的探索。Flink 强大的流批一体能力让我们可以很方便的去构建实时数仓体系架构。业务驱动着技术的发展,本着将业务做深、做厚的理念,我们将探索更多的应用场景,同时 Flink 与数据湖结合也是未来的研究方向之一。
其次,Flink CEP 的探索。利用 Flink CEP 强大的复杂事件处理能力,升级现有的 Data Stream 技术框架,并在风控、合规等场景推广使用。
最后,随着云服务向算力服务的不断引进,Flink 与 K8s 的深度结合也是我们后续的探索方向之一。通过 K8s 的资源调度能力实现资源稳步,提升资源的利用率。