基于数据库的事务消息解决分布式事务方案

转载请注明出处:http://www.cnblogs.com/lizo/p/8516502.html

概述

当单库已不能支撑当前业务的时候,我们往往都考虑进行分库(横向拆分或者纵向拆分)。但分库有个无法回避的问题,就是事务问题。网上有很多分布式事务解决方案,例如XA,TCC等,但是最常用,也是改造成本最低就是使用最终一致性来保证分布式事务。
比较常用的就是使用消息中间件(RabbitMq,RocketMq),通过事务消息来解决最终一致性。参考https://zhuanlan.zhihu.com/p/25933039?utm_source=tuicool&utm_medium=referral。

本篇文章将使用数据库的来达到最终一致性的实现方案。

名词解释

  • 主库-拆分前,业务访问的数据库
  • 分库-拆分后,部分业务数据放入到分库中

注:以下有些内容是在使用事务消息(无论是基于数据库还是基于消息队列)应该考虑的地方。

基于数据库的事务消息

事务消息

所谓基于数据库的事务消息,其实很好理解,就是在数据库中创建一个类似消息队列的表,用于保存事务消息。在拆分前,一个事务中,有多个主库的数据操作。如下图,

 

但是在拆分数据库后,有业务被拆分到分库中去了,这样,原有的单库事务被打破,但是通过把拆分出去的业务使用一个事务消息来代替(事务消息表也是在主库中,所以这里还是单库事务),后续再通过其他方式去执行该事务消息所对应的业务逻辑即可,这样,就可以达到最终一致性,如下图

 

事务消息执行器

前面说到了,事务消息需要一个处理器来进行执行事务消息所对应的业务逻辑。事务处理器应该是顺序的去读取并执行的。

设想一个场景:当出现某一条消息处理失败,如果执行器要等当前消息执行成功才继续往后执行(甚至该消息永远不会处理成功),那么会影响后续消息的执行,导致整个系统出现问题。

因此,消息处理器即要保证消息处理尽可能处理快,又能保证消息最终能执行成功。 在消息执行器中必须设置2个任务:

  • 第一个任务,消息处理任务,已最快的速度执行消息,如果消息处理失败了,跳过该消息继续执行后面的消息。
  • 第二个任务,消息校验任务,这个任务就是顺序检查消息,保证所有消息都执行成功,如果失败,进行重试,多次重试失败以后发出告警以让人工介入处理。 如下图

 

注:上图左边那个是消息队列及其处理状态

消息执行的特性

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

如何确认消息已执行成功

设想,如果分库业务执行成功(更新分库),然后去更新消息状态(主库),这样,又是一个夸库事务,所以,得想其他办法来避免,最简单的方法,就是在分库里面也建一个消息表,保存处理的成功的消息。这样,通过对比主库和分库的消息表,就知道哪些事务消息没有执行成功

消息处理器基本框架

前面介绍了,消息处理器的核心功能就:

  • 获取消息,并把消息发送给业务放处理
  • 保证消息执行的成功 

为了完成上面功能,需要消息处理任务和消息校验任务,通过定时调度任务来触发这2个任务(例如,5s触发一次)

 

消息处理任务

消息处理任务就是通过扫描待处理的消息,然后通知业务系统执行。

 

再次强调,消息处理任务不会管消息是否执行成功。都是按照消息队列表顺序执行下去。

消息校验任务

校验任务就是比较主库和分库中的消息记录(主库中记录的所有消息,分库中记录的执行成功的消息),对执行未成功的消息发起重试,如果多次重试失败则发出告警,需要人工介入。 

 

和基于消息中间件的事务消息比较

相同点

  • 都是采用异步确保最终一致性:
  • 可以控制异步执行消息的速率,可以利用RPC调用的负载均衡
  • 消息处理都必须支持重试和幂等性
  • 事务消息异步执行失败,都没办法回滚产生事务消息的事务 

不同点

消息事务的提交

使用消息中间件,一般都需要在代码中显示的编写提交中间件事务消息的代码,类似下面

public boolean transaction(String text){try {发送事务消息执行本地事务提交事务消息return true;} catch (TmcException e) {return false;}
}

但在实际项目中,事务的传播性的问题(spring 的事务注解是支持事务的传播性),就需要修改业务代码。但使用基于数据库的消息队列就没有这个问题

@Transactional
public void publishAS(String text){   执行本地事务逻辑插入事务消息
}

所以在既有代码改造上(特别是复杂系统中),使用数据库的事务消息可以减少代码的改动

不需要回调check

我们知道,在使用消息中间件的时候,都需要实现一个回调接口,当事务消息长时间没有commit的时候,会调用该接口来确认是否需要commit(例如发送消息成功,但是在commit的时候网络不可用)。而基于数据局的事务消息队列就没有这个问题

更多的数据库访问资源

基于数据库的事务消息也有一个比较明显的缺点:

  • 占用更多的数据库空间和数据库访问资源
  • 需要额外编写DAO层代码

小结

基于数据库和基于消息队列的事务消息的基本思路都一样,使用最终一致性来避免分布式事务带来的额外系统复杂性和代码开销。基于数据库的事务消息在既有业务改造中,代码变动较小,也不需要额外的引入消息中间件,但是带来的问题就是对数据库更多的访问。而基于消息中间件的问题就是如何避免在与消息中间件交互的出现问题的时候如何应对。当然,以上只是我个人理解,如果系统有什么设计不合理或者有改进的地方,欢迎讨论。

转载于:https://www.cnblogs.com/lizo/p/8516502.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/267501.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

websocket 发送给前端一个对象_前端WebSocket封装

场景1: 只有单个长链接,不要求保活class WebSocketClass {constructor() {this.instance null;this.connect();}static getInstance() {if (!this.instance) {this.instance new WebSocketClass();}return this.instance;}connect() {this.ws new WebSocket(ws:/…

POJ1683 Puzzlestan ——Floyd传递闭包+Dfs

好久没写Dfs了,拿来练手。 WA了一次,没有判断中间的情况…… 解法:先用Floyd传递闭包处理哪些点一定要在一起、哪些点一定不能在一起,六重循环。 然后深搜,res[i][j]表示1,i这个物品在j这一行的匹配物品列编号。 没有最…

中service层的作用_浅析Java中dto、dao、service、controller的四层结构

目前我所在的项目组采用的是SpringBoot框架,前端使用BootStrapjQuery。SpringBoot是BS开发框架之一,不用单独开启tomcat服务器,目前比较流行,一般开发大型项目时会将所有的功能细分为许多小模块,每个模块都有dto、dao、…

SCCM 2007系列教程之六使用组策略实现SCCM客户端

SCCM 2007 安装光盘上提供了名为 ConfigMgr2007Installation.adm 的组策略管理模板,可用于配置客户端计算机的安装属性。1、使用 Windows 组策略对象编辑器等编辑器来将管理模板 ConfigMgr2007Installation.adm 导入新的或现有的组策略对象。(此文件可以…

强化学习

机器学习算法完整版见fenghaootong-github 强化学习原理(RL) RL与有监督学习、无监督学习的比较: 有监督的学习是从一个已经标记的训练集中进行学习,训练集中每一个样本的特征可以视为是对该situation的描述,而其labe…

python的tool模块_barktools-包含各种有用的python模块和脚本的包-Oscar Bark Modules Scripts...

作者:Oscar Bark### 作者邮箱:kurshid.ognianovprotonmail.com### 首页:https://github.com/BarkenBark/python-tools### 文档:None### 下载链接# barktoolsA collection of utilities I find useful. Yes.Modulesbase_utilsA collection of modules which only depend on the …

非常不错的Nodejs工具:http-console

http-console是一个用nodejs写的类似于CURL的第三方库文件. 可以很直观的发送http请求以及查看返回结果. 安装需求: 1, 安装nodejs 2, 安装npm 3, npm install http-console 我做了个简单的例子: 启动: http-console 127.0.0.1:3000 1, HTTP GET: http://127.0.0.1:3000/&g…

bzoj1058: [ZJOI2007]报表统计

哈哈set卡时过了。 set求前驱的方法:*--b.lower_bound(x) (想想写了splay的肉老师就很愉悦啊) 弄两个set,一个记录的是位置的值,一个是差值,MIN_SORT_GAP就很简单啊,插入的时候找前驱后继&#…

javascript对象包含哪些要素_重学JavaScript 对象

栏目为大家介绍JavaScript的对象,重新认识。这里我们继续学习两个比较重要的类型,就是 Object 和 Symbol。我们主要讲的是 Object,相对 Object 来说 Symbol 只是一个配角。关于对象这个概念大家非常早就会接触到了,其实人大概在 5…

【iOS开发必收藏】详解iOS应用程序内使用IAP/StoreKit付费、沙盒(SandBox)测试、创建测试账号流程!...

Himi 原创, 欢迎转载,转载请在明显处注明! 谢谢。 原文地址:http://blog.csdn.net/xiaominghimi/article/details/6937097 终于在11月公司的游戏即将上线了,那么对于iOS游戏来说当今都是内置道具收费属于主流&#xf…

「BZOJ2879」[Noi2012]美食节

这道题就是 「BZOJ1070」[SCOI2007]修车 的加强版 如果一开始把全部边连上会T 优化的方法是只连用到过和下一次增广可能用到的边。 1 #include<bits/stdc.h>2 using namespace std;3 const int N50,M110,NN100010,oo1e9;4 int n,m,cost[N][M],tot,s,t,p[N],rank[NN],c[NN…

不越狱换壁纸_终于来了!iOS 14.3 正式版,可自动定时换壁纸

嘿嘿&#xff0c;我没有猜错吧&#xff01;iOS 14.3 正式版会在12月15日凌晨时段发布&#xff0c;在前几天我就有提到&#xff0c;这一天会发布&#xff0c;主要是与新品 AirPods Max 发售时间与iOS 14.3正式版发布时间一致。其次这次发布iOS 14.3正式版更新内容与 iOS 14.3 RC…

Hibernate【inverse和cascade属性】知识要点

Inverse属性 Inverse属性&#xff1a;表示控制权是否转移.. true:控制权已转移【当前一方没有控制权】false&#xff1a;控制权没有转移【当前一方有控制权】Inverse属性&#xff0c;是在维护关联关系的时候起作用的。只能在“一”的一方中使用该属性&#xff01;Inverse属性的…

[转]HOWTO do Linux kernel development - take 3 (中文版)

打好linux基础&#xff0c;不断的跟随这篇文章中的建议&#xff0c;适应linux kernel开发的流程。虽然需要很久甚至几年的时间&#xff0c;但我相信坚持就会前进&#xff01;加油&#xff01; HOWTO do Linux kernel development - take 3 (中文版) 译者&#xff1a;张乐 rober…

中list如何清空_如何根据索引删除 list 中的元素

这个问题很简单, 首先想到的就是a list(range(10)) del a[2]这个就可以很方便的删除掉 a 中的第 3 个元素.如果我想删除多个元素怎么办, 比如我想删除第 3, 4, 5, 6 个元素? 这个也很好办:a list(range(10)) del a[2:6]那么我要删除的元素的索引不连续呢? 比如我要删除第 3…

sql server紧急状态下登录脚本

--打开xp_cmdshell功能 EXEC [sys].[sp_configure] configname xp_cmdshell, -- varchar(35)configvalue 1 -- int 4 RECONFIGURE WITH override--修改注册表&#xff0c;修改身份验证为混合验证方式 USE [master] GOEXEC xp_instance_regwrite NHKEY_LOCAL_MACHINE, NSoftwa…

第一次项目之后...

从开始学习php不知不觉已经过去两个多月了&#xff0c;其中经历了各种各样以前没有经历过的生活和学习&#xff0c;在将近三个月的学习生活中我完成了第一个php项目。要说感觉&#xff0c;还真有些奇特&#xff0c;从开始连php是什么到现在能够亲手写出一个像模像样的网站就好像…

查询时拼接两列数据_如何用VBA代码查询两列数据差异?

爱就一个字&#xff0c;我只说一次……北京市第三交通委提醒您&#xff1a;代码千万条&#xff0c;注释第一条&#xff0c;命名不规范&#xff0c;修订两行泪……咳&#xff0c;给大家拜晚年了&#xff0c;再提前祝大家元宵快乐……我们今天和大家分享的内容是如何用VBA代码查询…

setTimeout详解

https://www.cnblogs.com/wzndkj/p/7069331.html 一、setTimeout基础 setTimeout(func|code,delay);第一个参数表示将要推迟的函数名或者一段代码&#xff0c;第二个参数表示推迟执行的毫秒数eg: console.log(1); setTimeout(console.log(2),1000); console.log(3);answer: 1 3…

Kappa电商负责人顾皓澜:电商业务一直保持盈利

Kappa电商负责人顾皓澜&#xff08;TechWeb配图&#xff09; 【TechWeb报道】10月初&#xff0c;闹得沸沸扬扬的淘宝商城事件吸引了无数互联网用户的目光&#xff0c;处于漩涡中心的淘宝商城当仁不让地挤入话题排行榜&#xff0c;商城上大小卖家的命运也牵动了众多消费者的心。…