文档章节

一文教你迅速解决分布式事务 XA 一致性问题

腾讯云加社区
 腾讯云加社区
发布于 2017/09/04 13:00
字数 3448
阅读 21
收藏 0
点赞 0
评论 0

欢迎大家关注腾讯云技术社区,我们将为大家推荐技术精品文章哦~

作者:腾讯云数据库团队 

近日,腾讯云发布了分布式数据库解决方案(DCDB),其最明显的特性之一就是提供了高于开源分布式事务XA的性能。大型业务系统有着用户多、并发高的特点,在这方面,集中式数据库(单机数据库)的性能很难支持,因此主流的互联网公司往往采用分布式(架构)数据库,物理上利用更多的低端设备,逻辑上对大表水平拆分支撑业务的需要。

虽然分布式数据库能解决性能难题,但事务一致性(Consistency)的问题,却很难在分布式数据库上得到解决。

分布式事务老大难题

数据一致难以实现

众所周知,一个事务所做的更新,分布式数据库系统内部多个独立的数据节点完成(每个节点的本地事务是这个全局事务的一个事务分支),在这样一个全局事务提交期间,有可能某些事务分支无法成功提交。

针对这一问题,虽然业内早已存在理论解决方案——二阶段提交协议(简称2PC),并延伸出分布式事务(简称XA)的解决方案。但业内却少有工程化实现且大规模应用的案例。而腾讯云分布式数据库DCDB,却已在内部业务中应用多年。

(图:二阶段提交算法)

目前DCDB已应用在腾讯内部90%以上的交易、计费业务,并且三一重工(树根互联)、汇通天下(G7)、阅文集团(起点/创世中文网等)、微众银行、和泰人寿、威富通等都在该产品。

腾讯云首发分布式数据库XA

支持MySQL 5.7

腾讯云分布式数据库DCDB,是基于腾讯金融级数据库(公司内部代号TDSQL)云化改造而来的兼容MySQL协议的分布式数据库。现如今,腾讯云DCDB已经正式在MySQL 5.7(percona分支)协议上支持分布式事务XA,并已在腾讯云公有云、金融云发布供开发者使用。开发者可以通过申请DCDB实例,并在初始化后,连接实例运行如下sql进行初始化:

MySQL> xa init;

Query OK, 0 rows affected (0.03 sec)
注意:初始化xa前,请开启强同步复制能力,另外该sql会创建xa.gtid_log_t,用户在后续使用中万勿对其进行任何操作。

为更好的支持分布式事务,DCDB还新增了SQL命令:

1)SELECT gtid(),获取当前分布式事务的gtid(事务的全局唯一性标识),如果该事务不是分布式事务则返回空;
gtid的格式:
‘网关id’-‘网关随机值’-‘序列号’-‘时间戳’-‘分区号’,例如 c46535fe-b6-dd-595db6b8-25

2)SELECT gtid_state(“gtid”),获取“gtid”的状态,可能的结果有:
a)“COMMIT”,标识该事务已经或者最终会被提交
b)“ABORT”,标识该事务最终会被回滚
c) 空,由于事务的状态会在一个小时之后清楚,因此有以下两种可能:
1) 一个小时之后查询,标识事务状态已经清除
2) 一个小时以内查询,标识事务最终会被回滚

3) 运维命令:
xa recover:向后端SET发送xa recover命令,并进行汇总
xa lockwait:显示当前分布式事务的等待关系(可以使用dot命令将输出转化为等待关系图)
xa show:当前网关上正在运行的分布式事务

以Python为例,可以对转账业务进行如下编码:

db = pyMySQL.connect(host=testHost, 
port=testPort, user=testUser, password=testPassword, database=testDatabase)
cursor = db.cursor()
try:
     cursor.execute("begin")

        #为一个账户Bob的余额减1
        query = "update t_user_balance SET balance = balance - 1  where user='Bob' and balance>1)
        affected = cursor.execute(query)
        if affected == 0: #余额不足,回滚事务
            cursor.execute("rollback")
            return

        #为一个账户John的余额加1
       query = "update t_user_balance SET balance = balance + 1  where user='John')
        cursor.execute(query)

      #为了安全起见,建议在这里执行‘SELECT gtid()’获取当前事务的id值,便于后续跟踪事务的执行情况

        #提交事务
        cursor.execute("commit")
    except pyMySQL.err.MySQLError as e:
        #发生故障,回滚事务
        cursor.execute("rollback")

分布式事务的好处在于会大大降低应用开发难度,因为在某些不支持XA的数据库中,需要业务系统通过特殊并且巧妙的设计,而非利用数据库来解决事务中数据不一致等问题。这种对应用开发者的技术水平要求很高,越是复杂的业务系统,越会增加开发成本和技术门槛,这是业内大多数开发者面对分布式数据库时,只能望而却步的主要原因。

腾讯云DCDB XA关键实现方案

1、DCDB架构介绍
腾讯云DCDB整个集群架构简图如下图,MySQL采用主从节点配置(也叫作主备)一套主从节点叫做SET,在每一个SET外配置网关(TProxy),形成一个物理分片(Shard)。

DCDB后端是MySQL(或其分支版本)数据库,目前腾讯云公有云发布支持XA的版本是基于MySQL 5.7.17(percona分支)。

2、网关(TProxy)与XA
网关是用于接收请求并与后端MySQL建立连接的网络模块。网关可以用两种模式工作,一种称为noshard,此模式下网关不处理/不解析SQL语句,透明转发请求和应答。另一种模式称为shard(分布式,即支持自动水平分表)模式下,TProxy会解析SQL并转发到不同的数据分片。

在实现XA之前,网关不允许在一个事务中向多个SET发送DML语句。因为未实现二阶段提交(2PC)时,事务采用一阶段提交,如果分布式中某一个SET提交失败了或回滚了,那么这个分布式事务就处于不一致的状态。


(网关的工作方式)

二阶段提交中需要的事务管理器(TM)。为了解决容灾、简化架构,腾讯云DCDB将TM实现在TProxy中,而DCDB的网关是一个无状态的模块,通过这一架构,DCDB XA可以支持:

(1)、分布式事务对业务透明,兼容单机事务语法(start transaction/commit/rollback/savepoint);

(2)、每个网关都可以独立接受和处理事务请求,且无需与其他网关进行协调节点故障不丢失事务;

(3)、允许显式事务中多条语句分别发给多个分片;

(4)、网关无需持久状态,无需容灾,可以随时经由调度集群退出或加入集群,且性能可以扩展;

(5)、支持autocommit下单条语句写访问多个分片等。

DCDB网关还允许以流式处理方式运行group by、order by,流式处理让这类操作变得非常方式非常高效;网关还支持两个Shard使用shardkey(分表键)做等值连接,以及使用shardkey的子查询。

未来,腾讯云还计划支持分布式JOIN、Sparksql、二级分区等高级功能,兼容更多MySQL高级语法。

3、强同步与XA
由于腾讯云DCDB默认采用强同步复制,即主从节点数据完全一致,因此XA事务也遵循强同步的逻辑,即需等待从机确认数据同步后,才给业务以应答(commit)。基于强同步,在以下两种异常情况下,DCDB XA可轻松应对。

(1)、主节点故障时,已确认事务数据不会丢失:主节点故障那么拥有最新数据和binlog的从机就被选为主节点,这其中的数据也包括所有已经向用户确认完成提交的事务的数据。

(2)、原主节点恢复后重新加入集群,未确认事务自动闪回:原主节点恢复重新接入集群,它将作为从机运行,此时他可能存留多余的已提交事务(此时事务并未得到强同步同步确认,即原备机并没有相关数据),那么这些事务会被闪回。虽然这些事务可能已经在原主节点的MySQL内部完成提交,但由于强同步机制,他并不会向客户端返回commit语句,这意味着仍被视为一个未完成的事务。因此,这些事务的闪回了也并没有破坏数据库的ACID属性。这里值得说的是,闪回flashback是基于binlog生成做逆操作,它与数据库回滚并不同rollback,闪回可以做DDL操作。

腾讯云DCDB的强同步为腾讯金融级数据库自研的一项能力,性能比官方半同步大幅提高,几乎等于异步复制性能,腾讯云DCDB在腾讯内部应用多年,未发生过一起因为主从切换、故障带来的数据误差。而且,从性能上,也撑住了腾讯公司各类大型运营活动如红包、各类游戏大型推广等海量并发,其主要原因是强同步采用异步提交/等待方式,且不占用数据库工作线程。

4、并发控制与隔离级别
为了达到数据一致性和性能的平衡,分布式事务的关键是数据库隔离控制。XA的隔离级别最高可以达到serializable(完全串行化),该级别将不存在幻读的问题,serializable级别可以通过设置SET global tx_isolation='serializable'来对DCDB所有物理分片(和其上承载的MySQL数据库)进行设置。当然,也可以通过调整隔离级别以调整数据库实例性能,理论上,Read Uncommitted性能最高,但可能存在脏读、幻读的情况。


ANSI/ISO定义的SQL-92
标准定义的四种隔离级别

5、分布式事务处理算法
前面讲到,腾讯云DCDB的网关在shard模式下已经能够解析SQL语句,腾讯云在网关上实现TM以使得XA最具效率。为此,我们在网关中实现TM中的协调器(coordinator),并在网关中维护每个XA的状态,记录好每个XA写入的SET,然后在提交阶段做两阶段提交即可,大致流程如下:


(1)、网关在执行一个事务的insert/update/delete语句时,会记录这个语句修改了哪个SET;

(2)、SET时会发送一个XA START在这个SET上面启动事务分支;(注:XA事务开始时,并不确认事务将以哪种提交方式执行,因此总是以xa start来开启一个事务);

(3)、检测是否影响SET个数≤1,若是,则直接做一阶段提交(xa commit one phase)。

(4)、影响SET个数≥2,则改为做两阶段提交:

1)网关首先发送xa prepare‘gtid’ 给参与的SET(大于等于2个SET);
2)SET接受到xa prepare应答ok(表示成功确认);
3)收到成功确认后,写入XA对应的commit log,再发送xa commit‘gtid’参与SET;
4)如果有SET返回了错误,或者写入commit log失败,那么网关发送 xa rollback‘gtid’给相关SET,这样这个全局事务就实现了回滚。

腾讯云DCDB的commit log是在SET中存储,这个步骤是批量完成的——网关后台线程会汇集正在提交的分布式事务然后在独立的连接和事务中完成对每个SET的写入,并且每个事务的commit log只写入一个SET中,因而这个开销并没有显著增加事务的提交耗时或者降低TPS。而且,依赖腾讯云DCDB已有的强同步和容灾特性,只要XA成功写入了commit log,就意味着数据已经写入从机。

虽然绝大多数的XA事务可以正常执行。但极少数的异常情况还是会影响整个集群稳定性,因此,腾讯云设计了agent(监控模块),在故障后继续协助完成本地MySQL上面prepared事务的提交,即agent会解析commit log,并根据异常处理本地仍然处于prepared的事务数据;如果commit log上面没有事务的提交决定的话,agent也会回滚超时未被提交的prepared本地事务。

虽然在MySQL 5.5、5.6等版本早已实现XA,但这两个版本相对于5.7仍然有性能不足,因此腾讯云目前只在公有云上基于5.7.17支持XA版本。如今,腾讯云在MySQL 、percona、MariaDB等分支中做了大量优化和相关bug修复(部分已经提交到社区修复patch或开源),未来腾讯云还将继续致力于新特性的开发和相关Bug的修复,为众多有需要的企业,提供更好的分布式数据库支持。

相关阅读

关于分布式“缓存”的思考

分布式锁服务关键技术和常见解决方案 ( 上)

轻松搞定对容器实例日志设置定期清理和回卷

此文已由作者授权腾讯云技术社区发布,转载请注明文章出处
原文链接:https://cloud.tencent.com/community/article/120564
获取更多腾讯海量技术实践干货,欢迎大家前往腾讯云技术社区

© 著作权归作者所有

共有 人打赏支持
腾讯云加社区
粉丝 79
博文 99
码字总数 244836
作品 0
深圳
分布式服务的事务如何处理

首先是不建议采用XA两阶段提交方式去处理分布式事务,要知道要能够支持XA分布式事务,必须是要实现XA规范才可以,而Service本身是无状态的,如果这样去做了等于是把Service内部的东西暴露了出...

rock912 ⋅ 2016/07/14 ⋅ 0

分布式事务;蚂蚁金服核心金融场景下的演进

  【IT168 评论】本文根据尹博学在2018年5月10日在【第九届中国数据库技术大会】的现场演讲内容整理而成。   讲师介绍:   尹博学,蚂蚁金服资深技术专家,目前负责数据中间件技术方向...

it168网站 ⋅ 05/23 ⋅ 0

深度| 一篇文章为你解读SOFA-DTX 分布式事务的设计演进路线

小蚂蚁说: 本文介绍了蚂蚁金服在分布式事务上,经过多年发展,服务于内外部大量不同业务,沉淀出的一整套包含TCC、FMT、XA模型的分布式事务解决方案。并且在持续对外输出的过程中,进一步打...

兔子酱 ⋅ 06/07 ⋅ 0

分布式服务的事务如何处理?比如dubbo,服务与服务之间的事务怎么处理比较好,现在有没有开源的解决方案?

作者:何明璐 链接:http://www.zhihu.com/question/29483490/answer/98237582 来源:知乎 著作权归作者所有,转载请联系作者获得授权。 首先是不建议采用XA两阶段提交方式去处理分布式事务,...

小麋鹿666 ⋅ 2017/01/28 ⋅ 0

GTS解密--GTS的原理、架构与特点

作者 赵成 日期 2018-01-01 标签 分布式事务 , GTS , Global Transaction Service, 柔性事务, TCC , XA两阶段提交协议 全局事务服务(Global Transaction Service,简称 GTS)是阿里新推出的...

chengxiaozc ⋅ 01/05 ⋅ 0

聊聊分布式事务

事务就是一个会话过程中,对上下文的影响是一致的,要么所有的更改都做了,要么所有的更变都撤销掉。就要么生,要么死。没有半死不死的中间不可预期状态。 参考下薛定谔的猫。 事务是为了保障...

tantexian ⋅ 2016/05/10 ⋅ 0

k神吹水之 聊聊分布式事务 转载

事务就是一个会话过程中,对上下文的影响是一致的,要么所有的更改都做了,要么所有的更变都撤销掉。就要么生,要么死。没有半死不死的中间不可预期状态。 参考下薛定谔的猫。 事务是为了保障...

恶魔永生 ⋅ 2015/01/27 ⋅ 0

干货|一篇文章带你学习分布式事务

小蚂蚁说: 分布式事务是企业集成中的一个技术难点,也是每一个分布式系统架构中都会涉及到的一个东西,特别是在这几年越来越火的微服务架构中,几乎可以说是无法避免,本文就围绕分布式事务...

兔子酱 ⋅ 05/28 ⋅ 0

深入理解分布式事务

Spring事务本质是单机下的事务,是由数据库本身保证的。今天,我将介绍一种比较复杂的事务:分布式事务。 1 什么是分布式事务 分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以...

小车车 ⋅ 2016/08/10 ⋅ 0

深入理解分布式事务

Spring事务本质是单机下的事务,是由数据库本身保证的。今天,我将介绍一种比较复杂的事务:分布式事务。 1.什么是分布式事务 分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以...

xboy_ly ⋅ 2016/08/25 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

个人博客的运营模式能否学习TMALL天猫质量为上?

心情随笔|个人博客的运营模式能否学习TMALL天猫质量为上? 中国的互联网已经发展了很多年了,记得在十年前,个人博客十分流行,大量的人都在写博客,而且质量还不错,很多高质量的文章都是在...

原创小博客 ⋅ 19分钟前 ⋅ 0

JavaScript零基础入门——(十一)JavaScript的DOM操作

JavaScript零基础入门——(十一)JavaScript的DOM操作 大家好,欢迎回到我们的JavaScript零基础入门。最近有些同学问我说,我讲的的比书上的精简不少。其实呢,我主要讲的是我在开发中经常会...

JandenMa ⋅ 今天 ⋅ 0

volatile和synchronized的区别

volatile和synchronized的区别 在讲这个之前需要先了解下JMM(Java memory Model :java内存模型):并发过程中如何处理可见性、原子性、有序性的问题--建立JMM模型 详情请看:https://baike.b...

MarinJ_Shao ⋅ 今天 ⋅ 0

深入分析Kubernetes Critical Pod(一)

Author: xidianwangtao@gmail.com 摘要:大家在部署Kubernetes集群AddOn组件的时候,经常会看到Annotation scheduler.alpha.kubernetes.io/critical-pod"="",以表示这是一个关键服务,那你知...

WaltonWang ⋅ 今天 ⋅ 0

原子性 - synchronized关键词

原子性概念 原子性提供了程序的互斥操作,同一时刻只能有一个线程能对某块代码进行操作。 原子性的实现方式 在jdk中,原子性的实现方式主要分为: synchronized:关键词,它依赖于JVM,保证了同...

dotleo ⋅ 今天 ⋅ 0

【2018.06.22学习笔记】【linux高级知识 14.4-15.3】

14.4 exportfs命令 14.5 NFS客户端问题 15.1 FTP介绍 15.2/15.3 使用vsftpd搭建ftp

lgsxp ⋅ 今天 ⋅ 0

JeeSite 4.0 功能权限管理基础(Shiro)

Shiro是Apache的一个开源框架,是一个权限管理的框架,实现用户认证、用户授权等。 只要有用户参与一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户...

ThinkGem ⋅ 昨天 ⋅ 0

python f-string 字符串格式化

主要内容 从Python 3.6开始,f-string是格式化字符串的一种很好的新方法。与其他格式化方式相比,它们不仅更易读,更简洁,不易出错,而且速度更快! 在本文的最后,您将了解如何以及为什么今...

阿豪boy ⋅ 昨天 ⋅ 0

Python实现自动登录站点

如果我们想要实现自动登录,那么我们就需要能够驱动浏览器(比如谷歌浏览器)来实现操作,ChromeDriver 刚好能够帮助我们这一点(非谷歌浏览器的驱动有所不同)。 一、确认软件版本 首先我们...

blackfoxya ⋅ 昨天 ⋅ 0

线性回归原理和实现基本认识

一:介绍 定义:线性回归在假设特证满足线性关系,根据给定的训练数据训练一个模型,并用此模型进行预测。为了了解这个定义,我们先举个简单的例子;我们假设一个线性方程 Y=2x+1, x变量为商...

wangxuwei ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部