初遇-分布式事务

一九年十二月份的时候,老大安排了我写个商户分润、以及财务审核入账的功能。大致的业务就是定时任务计算完商户分润之后,就会根据日期、交易类型、商户号作为唯一键。生成多笔分润记录。然后财务的同事进行审核之后,便调用账户系统入账的接口,将分润录入到商户的账户里去。…

当时由于我在写的财务审核的功能是在运营平台写的,那时运营平台连接的主库(读写分离),本地开发完以后,功能方面基本也没什么问题。直至有天,老大觉得运营系统连读写都连主库比较耗损资源。于是就将运营平台的数据库配置改为连从库。

财务的同事突然在某天反馈,点击审核之后,明明已经成功了。但是无效果,状态还是审核入中,于是她多点了几次。…当时我想完了,肯定出问题了。于是我便查看记账明细流水,果然发现了多了一笔重复入账的分润记录。于是我马上向老大反馈,由于正好前天改了数据库连接的配置,老大说,可能是主从延迟导致了。…

吸取了当时教训,我便改成了审核入账这块强制查主库,并且通过悲观锁锁住这条记录,在状态更改前,不允许任何读写操作。 写完之后,我特意用1000条线程模拟多个财务同时审核的情况。确认在性能方面也没问题之后,我便信誓旦旦的提交了代码。…

HintManager hintManager = HintManager.getInstance();
//强制查主库
hintManager.setMasterRouteOnly();
...
if (hintManager != null) {
    hintManager.close();
}

四个多月过去了,商户分润这块功能仿佛岁月静好。五月中旬的时候,我们老大把我叫了过去说,又有出现商户分润重复入账的问题了。我的天…这怎么可能…关键是过了那么久,也没有反馈这个问题了…在和老大过了代码之后,其实也没发现问题,老大说可能是强制查主库这块有问题。…只能对一条数据有效,但是多条可能就不行了。我说不会,这里我也有测试过,确实查的都是主库,并且又加悲观锁了。…

但老大说,还有最重要的一点是,每笔分润调用入账接口生成的流水号应该是固定唯一的才是,因为账户系统那边将入账流水号做了唯一键,这个才是为了防止重复入账的关键。

在老大的指导下,于是我在生成分润那里,加了个交易流水号的字段。生成每笔分润时,务必生成一个唯一的流水号。然后入账时用生成的流水号去进行入账。但是依旧没想通为什么还会重复入账,并且查看了当日的日志,也没发现什么系统异常,只是好像有一处自定义异常当时也没放心上。…

以为一切都相安无事的时候,结果财务的同事又开始反馈了。…商户分润的钱已经到商户的账户里,为什么商户分润那里的状态还是待审核。

…说实话,我慌了。…

于是我又过了一遍代码,结合之前看日志发现了一处业务异常。…终于发现了问题的所在。…因为商户审核这里,我之前还写了个批量审核的功能(for 循环 嵌套 try catch ),最关键的是我这个方法是还由事务控制,结合事务的原子性、一致性的特点,即使我前几笔状态已经更改为成功、并且调用入账接口入账成功了。但是只要遇到任何异常,便会进行回滚。也就是说商户分润即使已经入账成功了,但是分润记录的状态随着事务的回滚,依然是新增待审核的状态。…

所以这就遇到了分布式事务了。…

后来在老大的提议下,将for循环 + try catch 异常捕获,放到了审核方法的外面。并进行控制,这样就可以确保有入账失败,也不会影响到之前已经入账成功的记录。

说到这,可能又会童鞋在想。审核入账的状态即使已经成功了。但是调用账户系统出现异常(网络异常、系统异常)等等,如何确保账户系统已经入账成功了呢。接着如果了解到分布式事务的童鞋,又会牵扯到分布式事务的一些特性啥的。其实也没那么复杂,就好比我们写个新增、或者修改的方法,如果成功了就会返回一个受影响的行数。…这样就可以确保账户系统入账成功。
还有一点是,状态的兼容,当入账服务,返回重复入账,即表示已经入账成功,消费端进行状态的一个同步。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值