6.2 数据库事务异步化

    关于数据库事务异步化的典型场景,可以以一个互联网金融P2P平台进行交易系统改造中的客户还款场景为例。当一名借款人在该平台上成功借款后,例如借款金额为10万元,共有500人提供了借款,分为6期还款,每个月的最后一天为该借款的当月还款日。当一个月的月底到来时,这名借款人会到平台上进行还款操作,即保证自己账号中的金额大于当月所需还款金额+利息+平台管理费的总额之后,点击“还款”按钮进行真正的还款操作,此时按照业务逻辑的设计,该“还款”操作将包含的步骤如图6-3所示。

    空标题文档 - 图1

    图6-3 用户还款流程

    该步骤中仅仅示意了主要的核心功能,还没有考虑逾期还款、平台管理费、借/扣款人相关的积分和会员等级变化等业务逻辑。但从这个步骤大家可以看出扣款是一个要求事务一致性的典型场景,稍微数据不一致带来的后果都可能是成百上千(可能在某些借款项目中达到上百万的金额)的金额差异。所以在传统的实现方式中,整个扣款的逻辑代码都是在一个大的事务中,通过数据库的事务特性来实现这样一个稍显复杂的业务一致性。

    以还款为例,这样一个大的数据库事务中,每一位借款人进行的还款操作至少会引起500条还款详单(修改详单状态)+500次借款人账户表修改(扣款)+500名收款人账户表修改(收款),共计1500条数据表的修改,而平台的扣款日往往又都集中在自然月的最后一天,这样就导致在最后一天的最后几个小时,平台接收到密集的还款请求,使得数据库的压力持续高水位(超过95%)运行,用户在进行一次还款操作最长要等到10分钟后才收到系统返回的结果。这个问题的根本原因就是大的数据库事务对数据库的资源占用、表记录长时间被事务锁住带来的数据库请求排队。

    针对这类场景,解决平台性能问题的核心就是数据库事务的异步化。通俗来说,就是将大事务拆分成小事务,降低数据库的资源被长时间事务锁占用而造成的数据库瓶颈,就能大大提升平台的处理吞吐量和事务操作的响应时间。

    在实际的改造方案中,同样基于消息服务提供的异步机制,将整个还款流程进行异步化的处理(如图6-4所示),在五个主要处理流程间(还款开始、还款计算、还款计划分派、还款计划处理、详单处理)通过消息服务进行下一步业务的触发,执行的步骤如下:

    空标题文档 - 图2

    图6-4 异步化后的还款实现流程

    1)当用户在平台上点击了“还款”按钮后,会生成一条还款启动的消息,发送到消息服务上。

    2)“还款开始”程序接收到此消息后,首先执行“找到未还款的计划”,并同时进行“写入还款请求”和发送“还款计划计算消息”到消息服务上。

    3)“还款计算”接收到还款计划计算消息后,进行还款总额的计算,并同时进行占款和发起支付流程的消息到消息服务上。

    4)“还款计划分派”接收到支付流程的消息后,在给平台的账号转账的同时,发送分期支付消息,这里的消息会针对每一位还款详单中对应的还款人生成还款计划处理消息,这个处理是此次改造方案的核心,将之前在一个事务中处理500次还款处理的操作拆分为500个不同的事务。

    5)“还款计划处理”程序在接收到每一个还款详单支付请求的消息后,进行详单查找,计算还款详单,最后同时进行从借款人账户中进行扣占款以及发送还款详单处理的请求消息。

    6)最后则是“还款详单”接收到“详单处理”请求的消息后,依次进行给还款人账户加钱,更新详单表信息等操作。

    当然,在此过程中,一定要考虑到程序异常时对业务的回滚或重试机制,保障整个还款过程结果的最终一致。通过以上对还款事务异步化的处理,在不影响业务体验的前提下,整个平台对于还款的处理能力相比之前提升了20倍以上,因为大大减少了数据库记录的锁冲突,系统在还款高峰时期时用户体验基本跟平时没有太大的差异。