分布式事务之本地消息表解决方案(跨地区转账实际案例)

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 分布式事务之本地消息表解决方案(跨地区转账实际案例)

一、序言

1、现状


最近在做一个跨地区转账的功能,先说一下问题现状,公司业务范围主要分布在新加坡、香港和迪拜,相关交易、卡、账户等数据应各地区监管、合规要求必须分地区物理隔离,关于分库我们选择了中间件Sharding-Proxy,分片键为某个地区的区域码,所有的分片表都会带上区域码这个字段。


cf04f6870e584f7b9f50a7e9646cf3c6.png

如果是同地区转账,动账,交易记录读和写,带上当地区域码,所有的数据库请求都会由Sharding-Proxy路由到该地物理库,所以同地区转账同步在一个事务内跑完其实是没有问题的。


2、问题


如果是跨地区转账,比如从香港到迪拜,或者从新加坡到迪拜,那么问题就来了。虽然Sharding-Proxy本身支持分布式事务,但跨物理库分布式事务之前并没有过实际经验。


同时由于迪拜地区和新加坡、香港地域相隔很远,即使走专线网络传输时间也会比较长,而且转账业务中涉及到两个不同地区多个表的读写,余额变动时也会给出入账账户加上数据库行锁(排它锁),在大事务中很容易超时,同时接口响应慢也会影响用户体验。


于是,我们决定把出账和入账分离,入账通过MQ做成异步处理。


这个时候问题又来了,既然不能通过数据库本地事务保证ACID,那么分布式事务的问题该怎么解决呢?


二、方案探索


开源分布式事务解决方案有Seata,本身提供了ATTCCSAGA还有XA事务模式。但是该方案比较重量级、对外不透明,加上还要部署seata-server,额外增加了维护成本。

最后还是决定选择比较轻量级的解决方案,MQ+本地消息表+重试补发,大致流程如下。


671305731eab4b8988e820f0d2ecef15.png



先看出账方,出账记录、实际出账、本地消息表都在同一个事务,只要出账成功,那么本地消息表中一定会有转账相关的消息。


再看入账方,入账成功后,向ack_queue发送入账成功确认消息。


如果消费成功且入账成功,那么本地消息表中的消息会被逻辑删除,状态置为deleted。


如果消息发送失败、消费入账失败,本地消息表中消息状态会一直为undeleted状态,这时出账方会有一个补偿定时任务轮询本地消息表中状态为undeleted的出账消息。为了减少消息积压,当重试到一定次数后,停止发送消息到MQ,同时发送告警邮件给开发人员处理。


注意:入账方消费消息时需要做幂等,否则会重复入账,这里加上分布式锁就可以解决。


三、根据实际业务进行调整


实际我们的系统更加复杂,普通的转账是从A账户到B账户,而我们的转账A账户可能还会共享企业账户的余额。跨地区转账就更复杂了,每个地区都会有一个对公账户,资金变动流程如下:

60fc3ebbf0594f96a4aa7816c577db27.png

如果从香港地区的个人账户A转到迪拜地区的个人账户B,个人账户A和个人账户B又分别共享企业账户CACB的余额,那么完整的账户资金变动流程如下:

  1. 企业账户CA自动划账到个人账户A
  2. 个人账户A出账到对公账户PA
  1. 对公账户PB出账到个人账户B
  2. 个人账户B自动划账到企业账户CB

1、定时补偿扫表改为扫缓存


如果是直接轮询本地消息表,由于我们的本地消息表是广播表(PS:各个地区物理库都会有相同的表数据),查询时会随机查询各地区物理库,如果随机查询的是迪拜物理库本地消息表的记录,那么查询就会比较慢了。


因此在写完本地消息表后,我们同时会将本地消息表的记录写到Redis中,后续定时任务补偿直接扫缓存而不扫表。


同时在入账消费者方成功处理入账后,除了逻辑删除本地消息表中的记录(置为deleted),还要删除Redis缓存中的记录。


问题:写本地消息表和写Redis缓存这里可能会出现缓存不一致的情况,如果本地消息表写成功了,但Redis缓存写失败了,那么在做定时任务补偿扫缓存时会丢到该记录,这里缓存一致性需要保证。


2、出账异步处理


可以看到,出账时从企业余额共享账户CA个人账户A对公账户PA,中间会有3个账户的余额变动和出账记录,如果是同步返回,响应时间会比较长,也会影响用户体验,出账操作这里可以通过线程异步。


3、去掉ack_queue


目前系统出账方和入账方并没有跨系统,数据库也没有根据业务做垂直拆分,因此消费者入账成功后可以去掉发确认消息到ack_queue中,直接在消费端操作数据库将本地消息表中的记录状态置为deleted并删除缓存就好。


4、入账失败一直重试


跨地区转账业务这里还比较特别,有可能会出现公账的钱不够扣,导致交易失败。如果转入方公账钱不够扣就会导致入账失败,但转出方实际已经扣款成功了,因此入账操作必须成功,出账方定时任务针对本地消息表中的Pending记录会一直重试,直到入账方公账金额够扣,入账交易成功。

备注:在实际业务中,跨地区转账入账方真正到账是有延迟的,虽然出账和入账操作程序只需要在账面上进行余额的扣和减,但是比如从香港地区到迪拜地区,真正的钱要和当地结算后汇款过去才能到账的。


四、可能出现的系统瓶颈


1、各地区公账可能会出现抢锁超时


目前在每个地区都只设有一个公账账户,而在做跨地区转账时,每次都会操作出账方和入账方的公账余额。而在做余额变动时,将会对指定账户加数据库行锁(排它锁),虽然转账业务并不是很频繁,但是如果并发上来确实会导致过多线程等待数据库行锁释放,可能会出现锁争抢超时。


2、出账时异步扣款线程池大小不够用


由于扣账涉及多个账户的余额变动以及业务表记录,扣账操作响应时间会比较长,所以我们通过线程异步,提升用户体验。同时这里扣张操作核心线程数、阻塞队列长度和最大线程数不是很好把控,还是需要根据实际请求量进行调整,拒绝策略我们设置的是交由主线程执行。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
存储 SQL 微服务
常用的分布式事务解决方案(三)
常用的分布式事务解决方案(三)
|
2月前
|
关系型数据库 MySQL
常见分布式事务的解决方案(一)
常见分布式事务的解决方案(一)
|
3月前
|
存储 监控 固态存储
【vSAN分布式存储服务器数据恢复】VMware vSphere vSAN 分布式存储虚拟化平台VMDK文件1KB问题数据恢复案例
在一例vSAN分布式存储故障中,因替换故障闪存盘后磁盘组失效,一台采用RAID0策略且未使用置备的虚拟机VMDK文件受损,仅余1KB大小。经分析发现,该VMDK文件与内部虚拟对象关联失效导致。恢复方案包括定位虚拟对象及组件的具体物理位置,解析分配空间,并手动重组RAID0结构以恢复数据。此案例强调了深入理解vSAN分布式存储机制的重要性,以及定制化数据恢复方案的有效性。
96 5
|
29天前
|
程序员
后端|一个分布式锁「失效」的案例分析
小猿最近很苦恼:明明加了分布式锁,为什么并发还是会出问题呢?
32 2
|
1月前
|
分布式计算 NoSQL Java
Hadoop-32 ZooKeeper 分布式锁问题 分布式锁Java实现 附带案例和实现思路代码
Hadoop-32 ZooKeeper 分布式锁问题 分布式锁Java实现 附带案例和实现思路代码
45 2
|
2月前
|
消息中间件 中间件 关系型数据库
常用的分布式事务解决方案(四)
常用的分布式事务解决方案(四)
|
2月前
常用的分布式事务解决方案(二)
常用的分布式事务解决方案(二)
|
3月前
|
存储 NoSQL Java
一天五道Java面试题----第十一天(分布式架构下,Session共享有什么方案--------->分布式事务解决方案)
这篇文章是关于Java面试中的分布式架构问题的笔记,包括分布式架构下的Session共享方案、RPC和RMI的理解、分布式ID生成方案、分布式锁解决方案以及分布式事务解决方案。
一天五道Java面试题----第十一天(分布式架构下,Session共享有什么方案--------->分布式事务解决方案)
|
3月前
|
存储 固态存储 虚拟化
【vSAN分布式存储服务器数据恢复】VMware vSphere vSAN ESXi超融合HCI分布式存储数据恢复案例
近期,我司处理了一个由10台华为OceanStor存储组成的vSAN超融合架构,其中一台存储闪存盘出现故障,用户取下后用新的闪存盘代替,然后对该闪存盘所在的磁盘组进行重建,导致集群中一台使用0置备策略的虚拟机数据丢失。
88 6
|
3月前
|
存储 监控 数据可视化
性能监控之JMeter分布式压测轻量日志解决方案
【8月更文挑战第11天】性能监控之JMeter分布式压测轻量日志解决方案
96 0
性能监控之JMeter分布式压测轻量日志解决方案

热门文章

最新文章

下一篇
无影云桌面