数据库分库分表事务解决方案

一、概述

随着时间和业务的发展,数据库中表的数据量会越来越大,相应地,数据操作,增删改查的开销也会越来越大。因此,把其中一些大表进行拆分到多个数据库中的多张表中。 另一方面,在分库分表以后还需要保证分库分表的和主库的事务一致性。这片文章介绍一下:https://zhuanlan.zhihu.com/p/25933039?utm_source=tuicool&utm_medium=referral

本篇文章是基于非事务消息的异步确保的方式来完成分库分表中的事务问题。

二、需要解决问题

2.1 原有事务

由于分库分表之后,新表在另外一个数据库中,如何保证主库和分库的事务性是必须要解决的问题。

解决办法:通过在主库中创建一个流水表,把操作数据库的逻辑映射为一条流水记录。当整个大事务执行完毕后(流水被插入到流水表),然后通过其他方式来执行这段流水,保证最终一致性。

2.2 流水

所谓流水,可以理解为一条事务消息

上面通过在数据库中创建一张流水表,使用一条流水记录代表一个业务处理逻辑,因此,一个流水一定是能最终正确执行的.因此,当把一段业务代码提取流水中必须要考虑到:

  1. 流水延迟处理性。流水不是实时处理的,而是用过流水执行器来异步执行的。因此,如果在原有逻辑中,需要特别注意后续流程对该流水是不是有实时依赖性(例如后续业务逻辑中会使用流水结果来做一些计算等)。
  2. 流水处理无序性。保证即使后生成的流水先执行,也不能出现问题。
  3. 流水最终成功性。对每条插入的流水,该条流水一定要保证能执行成功

因此,提取流水的时候:

  1. 流水处理越简单越好
  2. 流失处理依赖越少越好
  3. 提取的流水在该业务逻辑中无实时性依赖

2.3 流水处理器

流水处理器即要保证流水处理尽可能处理快,又能保证流水最终能执行成功。

设想一个场景:当出现某一条流水处理失败,如果流失执行器要等当前流水执行成功才继续往后执行,那么会影响后续流水的执行,更严重的是一直卡在当条记录,导致整个系统出现问题

因此,流水执行器中设置2个任务:

  1. 第一个任务,流水处理任务,已最快的速度执行流水,如果流水处理失败了,也不影响后面流水处理
  2. 第二个任务,流水校验任务,这个任务就是顺序检查流水记录,保证所有流水都执行成功,如果失败,进行重试,多次重试失败以后发出告警以让人工介入处理。

2.4 流水处理完成

因为流水表是放在原数据库中,而流水处理完成后是操作分库,如果分库操作完成去更新老表流水消息,那么又是夸库事务,如何保证流水状态的更新和分库也是在一个事务的?

解决办法是:在分库中创建一个流水表,当流失处理完成以后,不是去更新老表状态,而是插入分库流水表中、

这样做的好处:

  1. 一般会对流水做唯一索引,那么如果流水重复多次执行的时候,插入分库流水表的时候肯定由于唯一索引检测不通过,整个事务就会回滚(当然也可以在处理流水事前应该再做一下幂等性判断)
  2. 这样通过判断主库流水是否在分库中就能判断一条流水是否执行完毕

三、流水处理器基本框架

流水处理器其实不包含任何业务相关的处理逻辑,核心功能就是:

  1. 通知业务接入方何时处理什么样的流水
  2. 检验流水执行的成功

注:流水执行器并不知道该流水表示什么逻辑,具体需要业务系统去识别后去执行相对应业务逻辑。

3.1 流水执行任务

流水处理调度任务就是通过扫描待处理的流水,然后通知业务系统该执行哪一条流水。

示意图如下:

3.2 流水校验任务

流水校验任务就是要比较主库和分库中的流水记录,对执行未成功的流水通知业务系统进行重新处理,如果多次重试失败则发出告警。

流程示意图:

四、为什么不用事务消息

由于是既有项目进行改造(本人从事互联网金融,所以是绝对不容忍有任何消息丢失或者消息处理失败),不使用事务消息有1个原因

  1. 需要额外引入消息队列,增加系统的复杂度,而且也需要额外的逻辑保证和消息队列通讯失败的时候处理
  2. 其实1不算是主要原因,而是因为事务消息需要手动的commit和rollback(使用数据库不需要),那么问题来了,spring中事务是有传递性的,那我们事务消息何时提交又是个大问题,例如 A.a()本来就是一个事务, 但是另外一个事务B.b()中又调用了A.a() 那事务消息提交是放在A.a()还是B.b()中呢?

原文发布于微信公众号 - java工会(javagonghui)

原文发表时间:2018-08-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏听雨堂

jquery获取父级一级节点的序号

结构为:          <ul id="zdcd" style="display:none">             <li>              ...

24560
来自专栏安恒信息

新一轮DNS钓鱼攻击已突破国内安全防线

近日,据国内领先的DNS服务提供商114DNS官网微博消息称:新一轮DNS钓鱼攻击已经突破国内安全防线,可能已经导致数百万用户感染。随后,其他安...

36060
来自专栏FreeBuf

揭秘银行木马Chthonic:网银大盗ZeuS的最新变种

说到Zeus/Zbot,做安全多多少少都会有所了解。Zeus是对金融系统威胁最大的僵尸网络之一,控制者借助僵尸程序窃取账户登录信息和信用卡号码。Zbot往往通过...

19970
来自专栏.NET开发那点事

nodejs+express+jade给我baby做个小相册

去年年底迎来了my little star。从此人生多了一个最重要的牵挂。生了宝宝全家人都太忙了。最近宝宝稍微大点了,终于有空可以研究下技术了。这是14年第一帖...

33350
来自专栏SAP最佳业务实践

SAP最佳业务实践:FI–自建资产(资本投资订单)(164)-6 KO04维护最终结算的结算规则

4.8 KO04维护最终结算的结算规则 在本步骤中,将维护最终结算的结算规则。投资订单的状态将被设置为“技术性结账”。这一状态将允许订单的最终结算。 必须成功...

42160
来自专栏blackpiglet

Discourse 搭建

Discourse 是由 Stack Overflow 创始人之一的 Jeff Atwood 主导的开源论坛项目,使用时能感受到和 Stack Overflow...

36420
来自专栏腾讯云安全的专栏

刚需 |Wannacry 勒索蠕虫病毒用户修复指引

22750
来自专栏FreeBuf

看我如何利用发现的漏洞接管D-Link路由器

我曾发现了D-Link路由器不同型号的多个漏洞,今天我要分享的是我最近发现的D-Link路由器的三个漏洞,综合利用这三个漏洞,可以获取D-Link路由器管理权限...

11420
来自专栏SAP最佳业务实践

SAP最佳业务实践:FI–应收帐款(157)-17中国金税

4.17 中国金税 在中国,所有的增值税一般纳税人必须通过金穗系统来开具增值税发票。 SAP系统提供与金穗系统的接口,以便利增值税发票的处理和打印。 销售与...

474120
来自专栏酷玩时刻

微信H5支付

先说一个事情。8月1号开始微信公众平台支付的开发配置页面迁移至商户平台 详细说明参考这个或者看下面的截图

1.4K20

扫码关注云+社区

领取腾讯云代金券