改进型账务系统设计研究

几个月前写的一篇,总是忘记,现在补发上来,提供参考,微信图始终没法高清,真不好!

摘要本文着重分析传统账务设计中存在的弊端,受比特币区块链系统架构启发下研究讨论在新形势下保证现有的业务功能不变的情况下如何改进系统以达到高吞吐量、高可用、高扩展新型账务系统

一、问题域

现如今无论是互联网时代还是数据时代抑或是人工智能时代,对于金融行业来说都迎来了一个前所未有的挑战,账务系统如何在爆发式大流量下还能保证稳定的可靠的服务。

我们先分析一下传统的账务系统结构与功能,从结构上看最主要两张表,一张分户账表,一张交易流水表。功能上基于现有的结构实现了基本的资金加减操作。其余的如每日的总分账汇总报表,账务平衡报表、与系统外部对账等功能是根据交易流水来做的,这样分析下来看,传统账务系统设计的分户账表只是充当了一个预记账的功能,客户来查询账户余额时,传统账务直接返回分户账记录的数据,那么问题来了,仅仅为了实现这个快速返回账户余额查询功能,传统账务在记账时,必然要采取数据一致性保护措施,以免某用户在并发情况下记错乱账的情况出现,一般情况下会采用悲观锁锁住待变化的分户账上某账户记录,如此往下,只要涉及账户变动都要锁住账户记录,这里的锁是一个逻辑概念,其实现方式通常有两种方案,一种是采用数据库提供的锁,这种属于低级别锁;一种是采用外部锁即所谓的分布式锁,当下流行的组件是ZooKeeper或ETCD来实现对应的锁功能,这样的锁是属于更高级的应用锁。无论采用那种方式提供锁功能,都得考虑扩展性,如果是采用的锁方案是第一种,那么必然会走分库分表的路线,因为数据库的锁是有限的,这种方案做前期实现简单,后期做数据迁移比较有难度,即使平滑迁移成功,整个系统也特别依赖一个一致性哈希组件,好在市场上已有比较成熟的组件可用如MyCAT,Vitess之类,尽管比较成熟,但仍有风险,环节越多风险越大,仅仅为了使用更多的锁,而不得不分库分表,不值当,因此很多账务系统架构师们纷纷采用分布式锁方案即采用ZooKeeper来实现锁,但问题又来了,采用分布式锁方案,抽象层级提高了,使用者简单,但风险提高了,分布式锁集群数据一致性是一个问题,业务系统与分布式锁集群网络交互是一个问题,业务系统与数据库系统交互网络又是一个问题,从实践案例看来,像账务这样的核心系统是不能采用第二种方案的。

在大流量下,传统账务系统设计方案是不能高效的处理交易的,此为问题一。

在“去中心化”的分布式理念一再升温下,数据可追溯性特征也是一个系统设计是否优秀的重要考量因素之一,虽然数据可追溯性是在分布式系统大行其道的情况下提出来的,最典型的应用案例是分布式任务追踪系统,其理论基础是Google开放出来的有关Dapper论文,然而在资金流上,业务方一直都有追踪资金流向的需求存在,但基于传统的账务系统设计是无法实现某一笔资金的追溯功能的,因为有了预记账功能,一旦某个账户有来款就自动放进了这个账户的资金池里即账户余额上,也实现不了某些特殊场景下的专款专用的条件了或者实现起来较为复杂,极不优雅。

“数据可追溯性”在传统账务系统设计中,虽有所提现,但仍然存在断层,此为问题二。

传统账务设计在新增特殊场景交易,前瞻性不足或者说应变能力较低。比如要增加多个二级账户场景,在传统账务系统实现较为麻烦,容易过度设计。此为问题三。

“数据安全性”级别较低,风险较高,数据连续性仅是明文显示,容易被篡改,此问题四。

二、解决方案

针对以上提到的四类问题,在保证传统账务系统设计下的业务功能不改变的情况下,我们提出一种改进型的账务系统设计方案,灵感来源于区块链系统架构。

问题一、大量锁造成系统交易处理效率低下

传统设计方案中无论是账户做加法操作还是做减法操作都需要锁,改进后的方案将不再使用锁,新方案不再采用预记账,仅使用一张流水表,账户信息仅作为总分账汇总和日账务平衡报表时辅助表使用,这样,账务的加减法操作,直接入库即可!

在讨论新方案具体实现之前,我们先讨论一下账务系统中交易事件模型,所有的账务交易事件都可以抽象成“收支转退”这四种交易模型,下面用图来展示,如下所示:

收款(或充值)模型:

支付(消费)模型:

转账模型:

一笔扣款,一笔充值明细

退款模型:

一笔扣款,一笔充值明细 与转账模型差不多,不赘述。

这几幅图中有几个要点需要关注的,第一、每一笔交易输入有谁负责挑选;

第二每一笔交易输出由谁负责计算;

如果这两个关键点都是由服务器端完成,那么新账务系统设计就又回到了原点,仍然回避不了锁的数量问题上了,且系统扩展性并没有得到提高。为什么?试想:如果由服务端完成交易输入挑选,那么势必引入锁,在整个交易完成之前必须锁定交易输入以防并发选中情况发生。所以新方案采用交易输入由客户端负责完成挑选,再并入交易时间、交易金额、账号等交易要素中一起送到后端账务记账系统,由账务记账系统完成交易输入选择是否合法(即检查被选中交易输入是否已被使用,金额是否足以交易,应由客户端完成校验),这样所有的交易过程将无需使用锁,即实现了无锁化交易。

如此设计,在保证安全性基础之上,从而使得系统吞吐量提升N个数量级,系统处理效能得到极大的提高!

问题二、数据可追溯性

对于账务系统来说,所有资金流的起点都是从加法(充值或转账)开始的,新方案采用为每一笔交易生成一个唯一ID(该ID是由账号+交易时间+交易金额+交易类型采用SHA256哈希之后生成),为了获取更好的系统处理性能,重复交易验证与交易合法性应交由数据库约束保证安全性,重复交易验证算法是如果唯一ID重复则拒绝入库;交易合法性验证:验证唯一ID值是否正确,不正确则拒绝入库或修改。由这一笔加法(充值)明细作为下一笔减法(支付)明细输入,如下图所示:

其中的Trace ID 是交易跟踪号,Parent ID是交易输入的Span ID ,Span ID是当前交易唯一ID,资金流的最初一笔交易明细Trace ID、Parent ID、Span ID三个ID是相同的。

如此设计,追溯一笔资金的来龙去脉流向变得相当容易,类似资金原路返回、风控冻结交易金额操作也会变得简单。

问题三、应变能力

业务有变化,新增账户种类,则由客户端完成,服务端存有数据备份。交易量上来,也不用担心,后端数据读写采用读写分离的策略,那么所有的交易几乎可以认为是无状态的交易,那么其拓展能力与web拓展能力是等同的

问题四、安全性

采用新方案使得系统处理能够无锁化,从而达到极大的提高系统吞吐量和处理能力。但这个交易过程中存在交易安全隐患,同一时刻只能保证一个合法客户端可以参与交易,这个问题容易解决,客户端每一次发起交易必须与后端通讯拿到一个合法Token,方可进行合法交易,拿到Token的客户端则为合法客户端,比服务端的Token小的客户端会立即失效,如此保证交易环境的安全。

二、结论

改进后的账务系统,由传统集中式设计方案过渡到分布式记账方案,但又不是完全与区块链系统架构一样,后端系统仍然保持了绝对的控制权,在非常高的吞吐量,处理能力基础之上又能兼顾扩展能力,应该说是目前较为合理的架构方案。

改进后的账务系统存在的缺点对于交互安全性要求高、网络通信频繁,网络通信频繁这个问题在如今进入高速网络时代,应该不算是问题了,但交互安全性需要精心设计,虽然后端仍然拥有绝对的控制权,对于伪终端的识别无论传统客户端还是改进后的账务客户端都是一个重点关注的问题。

三、后记

通常情况下,每一个支付公司系统模型,决不仅仅是一个客户端、一个服务端组成简单支付系统,而是由众多系统如支付网关、订单系统、商户管理系统等构成的一个复杂的支付系统,改进型账务系统只是提了一个关注点分离的分层架构参考模型即如何才能获取更高、更好、更优秀的IT系统。

然而,我们在做系统设计时,至今都规避不了康威定律,这是由人的本性决定的,一个好的系统设计仍然需要群策群力,然后由上至下进行推广,才有可能成功。

注:

交易输入 即区块链交易模型中的TXIN

交易输出 即区块链交易模型中的 TXOUT

康威定律大概意思是指无论系统如何设计,最终实际系统架构都朝着一个方向前进,即完全与集体的组织结构相一致

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181218G1J73M00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券