APP下载

MongoDB在银行海量历史交易数据查询中的应用

2021-08-19蔡培茂张申勇谭忠兵魏志军

现代计算机 2021年21期
关键词:副本集群账户

蔡培茂,张申勇,谭忠兵,魏志军

(北京理工大学珠海学院,珠海519088)

0 引言

账户历史交易数据查询服务是银行金融业务的重要组成部分,主要是指对客户的银行卡(借记卡、信用卡等)或者银行活期存折,在一段时间内发生存取款业务交易清单的检索。账户历史交易数据查询是银行信息化系统的不可缺少的功能,也是银行客户最常使用的功能之一,对本人交易历史全貌了解和掌握是银行客户的强烈需求。

对于账户历史交易数据查询功能,业内传统解决方案是基于关系型数据库的,一般采取主机分流做法,即事务型处理和分析型处理分离[1],也就是事务型业务处理由核心业务系统的关系型数据库来承担,再建立另外的一个关系型数据库来专门实现历史数据存储与查询,但在传统解决方案中,由于关系型数据库的局限,查询库中仅提供最近几年的客户交易明细,单次查询时间段跨度最长为一年左右,其余的交易历史数据多以光盘库、磁带库的形式存放,这样的做法查询效率低且成本高,一般用户只能查询近期数据,不能对历史数据全貌进行方便查询,并且查询条件单一,对多条件高级查询支持不足。近年来,随着各种便捷支付方式的普及,账户交易数据量呈现爆炸性增长,同时,客户交易数据类型也在快速变化,出现手机银行、网上银行、微信银行等不同使用方式,为了能够以较高的性能满足海量交易数据的查询需求,常常需要采取分库分表方式或采用分布式关系型数据库来解决[2],但这些方式部署、管理、配置复杂,扩容困难,并且造成开发难度大幅上升。由于传统关系数据库可扩展性差、数据模型死板、严格事务机制等原因[3],无法满足数据量巨大、高并发、高扩展和高可用的银行海量历史交易数据查询的需求[4]。

近年来,为了获得灵活的数据模型、分布式和横向扩展能力,各种新型的、非关系型数据库应运而生,这些数据库统称为NoSQL,NoSQL数据库类型多样,包括Redis、HBase、MongoDB等,这些NoSQL数据库可满足不同场景的应用需求[5]。为了更好地满足客户和监管机构等对于历史交易数据的查询要求,提高业务处理能力,改进客户体验,本文提出一种基于MongoDB的存储和查询银行海量历史交易数据的应用解决方案,实现银行海量历史交易数据的全量存储、多条件复杂查询、高效在线统计计算和系统的可扩展、高可用等。

1 MongoDB的特点

MongoDB是一个基于分布式文件存储的开源NoSQL文档数据库,由C++语言编写[6]。根据DB-En⁃gines发布的2021年2月份的数据库排名中,MongoDB排名第五,并且分数保持持续增长。

MongoDB具有高性能、高可用、易横向扩展、模式灵活、支持索引、支持聚合操作、支持动态查询等优势,文件存储格式是BSON格式,BSON是类JSON的一种二进制形式,支持内嵌的文档对象和数组对象。而关系型数据库基于单机架构,模式固定,不容易横向扩展,难以支撑系统所需要的海量数据。

银行交易数据具有规模大、增长速度快、结构易变等特点,查询要求高可用、高性能和查询条件复杂等,MongoDB的特点能够很好地满足银行历史交易数据存储和查询的需求,具体如下:

(1)高可用性。MongoDB提供副本集群架构,副本集中一组MongoDB实例保持相同数据集。通过部署副本集群,实现历史交易数据存储和查询系统的自动恢复、故障自动接管、提供7×24小时可用等。

(2)高扩展性。MongoDB提供分片集群架构,分片是指数据拆分并分散存放在不同机器上,为MongoDB实现横向扩展能力。通过部署分片集群实现历史交易数据的全量存储和检索,使客户能够看到其交易历史全貌,能够实现系统的平滑扩容。

(3)模式灵活。MongoDB提供灵活的BSON文档模型,无须预定义模式结构,文档中的键和值无须定义固定的类型和大小,非常适合交易数据结构易变的特点,方便支持新的支付方式,使开发能够快速迭代以响应业务需求的变化。

(4)高性能。MongoDB提供了多样性的索引支持和多种分片策略。通过设计合理索引和分片键、副本集多节点数据读取等方法,可以实现历史交易数据的高并发访问和快速响应。

(5)复杂查询。MongoDB支持丰富的查询语言、数据聚合框架等,能够满足历史交易数据多条件复杂查询的需要,这也是MongoDB相对其他NoSQL数据库的优势,如:HBase。

2 系统架构

交易数据查询具有大量高并发读操作的特征,传统主机架构性能扩展不易、成本高,为了降低核心业务系统的压力,业界普通采用主机分流。根据对Mon⁃goDB特点的分析,这里采用MongoDB作为主机分流数据库,将业务数据从现有主机或Oracle等关系型数据库实时同步复制到MongoDB,以实现客户对交易数据查询或统计分析,系统架构如图1所示。

图1 系统架构

图1 系统架构各组成部分说明如下:

(1)核心业务系统。该系统是现有银行核心业务系统,承担银行核心交易事务处理,交易数据存储在关系型数据库中,包括账户交易明细、客户回单信息、账户基本信息、客户基本信息等最新数据。

(2)采集层。该层实现从核心业务系统的异构数据库中实时同步数据到MongoDB中,这里使用Kafka实时监听核心业务系统中数据变动并同步至Mon⁃goDB。Kafka是由Apache软件基金会开发的一个开源的、高吞吐量的分布式发布订阅消息系统[7],非常适合实时数据的传输。采集层也可以采用市场上一些专门针对MongoDB的同步数据产品。

(3)数据层。该层采用MongoDB的副本集群、分片集群来存储海量历史交易数据,以实现高可用、高性能、高扩展等系统特性。MongoDB集群架构如图2所示。

(4)业务层。该层是查询业务的实现层,一般采取分层架构以实现系统功能的低耦合、高内聚的设计要求,如:数据访问层的职责是通过MongoDB驱动程序访问MongoDB中的数据;逻辑层的职责是根据客户请求实现业务逻辑的处理;控制层职责是适配不同客户端,实现请求流程控制与跳转。

(5)客户端。用户可以通过不同方式访问系统功能,如:手机App、网上银行、微信小程序、柜员机、银行内部系统等。

在系统架构中,数据层中MongoDB的部署模式是需要重点考虑的部分,为保证生产过程的高可靠和高可扩展,需要结合MongoDB副本集和分片机制来搭建MongoDB的分布式集群架构,如图2所示。

图2 MongoDB集群架构

为了实现交易数据查询系统的自动容错、自动故障恢复[8]和高可用,需要部署MongoDB副本集群,一般典型的副本集由3个以上具有投票权的节点组成,由于副本集中的节点都有可能成为主节点,所以副本集中的节点的硬件配置要保持一致。副本集除了实现高可用外,还有以下附加作用,如数据分发、读写分离和异地容灾等,所以副本集中成员节点的数量需要根据系统实际需求进行增减,但不能少于3个节点。

分片集群可以有效解决性能和扩容问题,但是分片需要更多的机器,管理复杂,因此在数据规模不大的情况下,使用副本集的方案就够了[9],不需要使用分片集群,然而,随着时间的推移和各类便捷的支付方式的普及,会出现数据量快速增长、访问性能下降等问题,同时,为了实现历史交易数据的全量存储和检索目标,最终是需要分片集群来解决的。分片群集的规模需要根据所需存储数据总量、并发量总数、缓存数据大小等因素来综合规划和确定。

为了提高路由的可用性和实现负载均衡,路由节点至少2个,可根据实际并发访问情况增加更多的路由服务器节点。

配置服务器存储了分片集群的元数据,为了保证高可用,所以配置服务器同样必须部署成副本集。

3 数据模型

银行业务中存在各种不同类型的账户,如:借记卡、信用卡、股票账户、基金账户等,每种账户的交易数据类型也不相同,并且随着业务的开展,还会出现新的账户类型和新的交易数据类型,因此存储交易数据的数据模型必须灵活和支持弹性扩展,以适应新业务发展需要。MongoDB是无模式数据库,提供非常灵活的文档数据模型,完全能满足银行业务的这种需求。MongoDB的BSON文档是一种模式自由的存储形式,能够动态地添加数据项,灵活性很高。

交易数据大多数情况下涉及客户信息、账户信息和交易明细三类。为了获得高效率的查询,设计两个集合来存储主要数据:客户账户集合customer和交易明细集合txdetail。

客户账户集合customer的文档格式示例如下:

交易明细集合txdetail的文档格式示例如下:

以上文档示例仅包括交易数据中最常用的基本信息,对于单据、证件影像数据,由于一般查询不会用到这些数据,因此应该设计单独的集合来存储,同时考虑在MongoDB中BSON文档有16MB大小的限制,所以,需要保存到MongoDB的GridFS中[10]。

4 索引与分片键

在基于MongoDB数据库的系统中,索引和分片键是非常关键的,下面结合银行海量历史交易数据查询的应用特点给出主要索引和分片键的设计策略。

4.1 索引设计

为了避免全集合扫描,提高查询性能,MongoDB提供了索引机制。在交易数据查询中,最常见的查询场景是根据账户编号、交易时间范围、交易金额范围等多个条件组合来查询交易明细集合txdetail,并且根据交易时间倒序排列,所以需要创建一个包含这些查询条件字段的组合索引。

MongoDB索引采用B-树结构,因此组合索引中的索引字段顺序非常重要,组合索引中索引字段的最佳排序方式是精确匹配的字段在前面、排序条件字段在中间,范围匹配的字段在最后。对于交易数据查询,账户编号是精确匹配、交易时间和交易金额是范围匹配、而交易时间常用于排序,所以对交易明细集合txdetail创建这个主要索引:db.txdetail.createIndex({account_no:1,tx_date:-1,tx_amount:1})。

4.2 分片键设计

为了存储和处理海量历史交易数据,需要借助MongoDB分片机制来实现。在MongoDB的分片集群中,分片键的设计是非常关键的,分片键决定了数据分布方式,直接影响集群的性能。设计分片键时需要综合考虑分片键的基数、分片键值分布、定向访问等因素,通常选择基数大、数值分布均匀、对主要查询具有定向能力的一个或多个字段组合来作为分片键。

交易明细集合txdetail会随着时间的推移,数据量会快速增长,达到非常大的规模,因此该集合需要进行分片。同时,大部分场景是根据账户编号、交易时间范围来查询交易数据。本系统的分片键设计应达到“分散写”和“集中读”的目标,从而提高系统性能。“分散写”是指从核心业务系统同步数据至MongoDB集群时,数据能够均匀地分布到集群中各分片服务器中,避免因总写某一分片服务器和某一分块而导致出现热点问题和超大块问题;“集中读”是指同一个账户的交易数据总是在同一个分片服务器中,查询时能够直接定向到该分片服务器进行数据读取,而不需要将查询分发到不同的分片服务器。

综上所述,对交易明细集合txdetail采用“交易账户编号+交易时间”作为分片键,“交易账户编号”在前面能实现“集中读”的目标,而加上“交易时间”能够增大分片键值基数,避免出现超大块问题,实现“分散写”的目标,操作命令如下:

对数据库启用分片:sh.enableSharding("数据库名")

对交易明细集合txdetail建立索引(前面已创建):

db.txdetail.createIndex({account_no:1,tx_date:-1})

对交易明细集合txdetail建立分片:sh.shardCollec⁃tion("数据库名.txdetail",{account_no:1,tx_date:1})

5 实现效果

MongoDB提供多种语言的驱动程序API,如:Java、Python等,可以采用这些语言来实现业务层,以下给出的Mongo Shell操作指令,可以很容易转化为相应开发语言API的调用。

图3 展示了历史交易数据查询的常见查询条件,其中基于账户、交易时间范围是最常用的查询,该查询的Mongo Shell操作指令如下:

图3 查询条件

图4 展示了历史交易数据查询结果,其中本页统计交由客户端实现,本次查询收支金额总计则由Mon⁃goDB的聚合框架来实现,具体Mongo Shell操作指令如下:

图4 查询结果

6 结语

本文给出了基于MongoDB实现银行海量历史交易数据查询的解决方案,通过对历史交易数据查询业务分析,结合MongoDB高可用、高性能、高扩展和模式灵活等特点,设计了系统架构、数据模型、合适的索引、分片键和系统实现效果。该方案能够实现银行交易数据查询能力从1年提升至10年或甚至全量数据,实现毫秒级快速响应,大大提升用户体验,并能够节省大量系统维护时间,提供7×24持续服务。另外,通过Mon⁃goDB存储了全量的客户信息和交易明细,为银行实现业务创新和为客户提供个性化服务奠定了基础。

猜你喜欢

副本集群账户
齐口裂腹鱼集群行为对流态的响应
如何切换Windows 10本地账户与微软账户
Windows10账户的删除、禁用与启用
国家知识产权局公告:专利证书改版
勤快又呆萌的集群机器人
上交所:将允许一人开设多个证券账户
投连险半月收益率红黑榜
新副本“战歌之城”怨灵BOSS面面观
《口袋西游—蓝龙》新副本“幽冥界”五大萌点
走出孤独囧境