近日,腾讯云发布了分布式数据库解决方案(DCDB),其最明显的特点之一就是提供比开源分布式事务XA更高的性能。大型业务系统具有用户多、并发度高的特点。在这方面,中心化数据库(单机数据库)的性能难以支撑。因此,主流的互联网公司往往采用分布式(架构)数据库,在物理上利用了更多的底层数据库。终端设备在逻辑上支持大表水平拆分的业务需求。虽然分布式数据库可以解决性能问题,但是事务一致性(Consistency)问题在分布式数据库上很难解决。分布式事务是个大问题。数据一致性很难实现。众所周知,一个事务完成的更新是由分布式数据库系统中多个独立的数据节点完成的(每个节点的本地事务是这个全局事务的一个事务分支),在这样一个全局事务提交过程中,是可能某些事务分支无法成功提交。针对这个问题,虽然业界已经有了理论上的解决方案——两阶段提交协议(简称2PC),并扩展了分布式事务(简称XA)的解决方案。但在行业内工程化实现和大规模应用的案例还很少。但是,腾讯云的分布式数据库DCDB在内部业务中已经使用了很多年。(图:Phase2提交算法)目前,DCDB已经应用于腾讯90%以上的内部交易和计费服务,以及三一重工(树根互联网)、汇通天下(G7)、阅文集团(启/创世中文互联网等)、微众银行、和泰人寿、微富通等都在这款产品中。腾讯云首款分布式数据库XA支持MySQL5.7腾讯云分布式数据库DCDB,是基于腾讯金融级数据库(公司内部代号TDSQL)云化改造的兼容MySQL协议的分布式数据库。今日,腾讯云DCDB在MySQL5.7(percona分支)协议上正式支持分布式事务XA,并发布在腾讯云公有云和金融云上,供开发者使用。开发者可以申请一个DCDB实例,初始化完成后,连接实例,执行如下sql初始化:MySQL>xainit;QueryOK,0rowsaffected(0.03sec)注意:在初始化xa之前,请启用强同步复制能力。该sql会创建xa.gtid_log_t,用户在后续使用中不得对其进行任何操作。DCDB为了更好的支持分布式事务,还增加了SQL命令:1)SELECTgtid(),获取当前分布式事务的gtid(事务的全局唯一标识),如果事务不是a则返回空分布式事务;gtid的格式:'网关id'-'网关随机值'-'序列号'-'时间戳'-'分区号',例如c46535fe-b6-dd-595db6b8-252)SELECTgtid_state("gtid"),获取“gtid”的状态,可能的结果有:a)“COMMIT”,表示事务已经或最终将被提交b)“ABORT”,表示事务最终将被回滚c)为空,因为交易状态会在一小时后清空,所以有两种可能:1)一小时后查询,说明交易状态已经清空2)一小时内查询,说明交易最终会滚动back3)运维命令:xarecover:backward终端SET发送xarecover命令并汇总xalockwait:显示当前分布式事务的等待关系(可以使用dot命令将输出转化为等待关系图)xa显示:分布式交易目前在网关上运行的ion以Python为例,可以将转账业务编码如下:db=pyMySQL.connect(host=testHost,port=testPort,user=testUser,password=testPassword,database=testDatabase)cursor=db...#余额不足,回滚交易cursor.execute("rollback")return#增加1个查询某账户余额John="updatet_user_balanceSETbalance=balance+1whereuser='John')cursor.execute(query)#为了安全起见,这里建议执行'SELECTgtid()'获取id值cursor.execute("commit")exceptpyMySQL.err.MySQLErrorase:#失败发生,回滚事务cursor.execute("rollback》)分布式事务的好处是会大大降低应用开发的难度,因为在一些不支持XA的数据库中,需要业务系统通过特殊巧妙的设计,而不是使用数据库来解决交易中的数据不一致,这对应用开发者的技术水平要求很高,越复杂的业务系统会增加开发成本和技术壁垒,这也是为什么m业内大多数开发者在面对分布式数据库时只能望而却步。腾讯云DCDBXA一键实现方案一、DCDB架构介绍腾讯云DCDB整个集群架构示意图如下图所示。MySQL采用主从节点配置(也叫master-slave)。一组主从节点称为SET,每个SET外配置一个网关(TProxy),形成一个物理分片(Shard)。DCDB后端是一个MySQL(或其分支版本)数据库。目前腾讯云公有云发布的XA版本是基于MySQL5.7.17(percona分支)。2、网关(TProxy)和XA网关是用来接收请求并与后端MySQL建立连接的网络模块。网关可以工作在两种模式,一种叫做noshard,网关不处理/解析SQL语句,透明转发请求和响应。另一种模式称为shard(分布式,即支持自动水平分表)模式,TProxy会解析SQL并转发到不同的数据分片。在实现XA之前,网关不允许在一个事务中向多个SET发送DML语句。因为是两阶段提交(2PC),所以事务采用一阶段提交。如果分布式中的某个SET提交失败或者回滚,那么分布式事务就处于不一致状态。(网关的工作模式)两阶段提交(TM)中需要的事务管理器。为了解决容灾和简化架构,腾讯云DCDB在TProxy中实现了TM,DCDB的网关是一个无状态模块。通过这种架构,DCDBXA可以支持:(1)分布式事务对业务透明,兼容单机事务语法(开始事务/提交/回滚/保存点);(2)、每个网关可以独立接受和处理交易请求,不需要与其他网关协调,不会因节点故障而丢失交易;(3)、允许显示事务中的多个语句被发送到多个分片;(4)、网关无需持久化状态,无容灾,可通过调度集群随时退出或加入集群,性能可扩展;(5)、支持autocommit将单个Statement写入多个分片等。DCDB网关还允许groupby和orderby流式运行,这样的操作非常高效;网关还支持两个分片使用shardkey(shardkey)进行等价连接,使用Subquery进行shardkey。未来,腾讯云还计划支持分布式JOIN、Sparksql、二级分区等高级功能,并兼容更高级的MySQL语法。3、强同步和XA由于腾讯云DCDB默认采用强同步复制,即主从节点数据完全一致,所以XA事务也遵循强同步逻辑,即需要等待供slave在响应业务前确认数据同步(commit)。基于强同步,DCDBXA可以轻松应对以下两种异常情况。(1)当主节点失效时,确认的交易数据不会丢失:如果主节点失效,那么会选择有***数据和binlog的从机作为主节点,数据也包括所有的datathathasbeenconfirmedtotheuser已提交事务的数据。(2)原主节点恢复并重新加入集群后,未确认的事务自动闪回:原主节点恢复并重新连接到集群,它将作为从节点运行,此时可能会保留冗余提交的事务(此时交易还没有得到强同步同步确认,即原机没有相关数据),那么这些交易就会被闪回。虽然这些事务可能已经在原主节点的MySQL内部提交了,但是由于强同步机制,他不会向客户端返回commit语句,这意味着它仍然被认为是一个未完成的事务。因此,这些事务的闪回并没有违反数据库的ACID属性。这里值得一提的是,flashback是基于binlog生成的逆操作。与数据库回滚不同,闪回可以进行DDL操作。腾讯云DCDB强同步是腾讯金融级数据库的自研能力。性能相比官方的半同步有很大的提升,几乎等同于异步复制的性能。腾讯云DCDB在腾讯使用多年。故障引起的数据错误。而且,在性能上,还支持腾讯各种大规模运营的海量并发,比如各种游戏的红包、大规模推广等。主要原因是强同步采用异步提交/等待方式,不占用数据库工作线程。4.并发控制和隔离级别为了在数据一致性和性能之间取得平衡,分布式事务的关键是数据库隔离控制。XA***的隔离级别可以达到serializable(全序列化),这个级别不会出现幻读问题。可序列化级别可以设置SETglobaltx_isolation='serializable'到DCDB(及其上托管的MySQL数据库)的所有物理碎片来设置它。当然,你也可以通过调整隔离级别来调整数据库实例的性能。理论上ReadUncommitted性能最好,但是可能会出现脏读和幻读。ANSI/ISO5定义的SQL-92标准定义的四个隔离级别。分布式事务处理算法XA***效率。为此,我们在gateway中实现TM中的coordinator,在gateway中维护每个XA的状态,记录每个XA写入的SET,然后在commit阶段做两阶段commit,大致过程为如下:(1)、网关在执行一个事务的insert/update/delete语句时,会记录下该语句修改了哪个SET;(2)、什么时候SET会发送一个XASTART在这个SET上开始事务分支;(注意:在一个XA事务开始的时候,并不确定事务会以哪种commit方式执行,所以一个事务总是以xa开始);(3)、检查受影响的SET数量是否≤1,如果是,则直接做Phase提交(xacommitonephase)。(4)如果受影响的SET数量大于等于2,则改为执行两阶段提交:1)网关先发送xaprepare'gtid'给参与的SET(大于等于2个SET);2)SET收到xaprepareresponseok(表示确认成功);3)收到成功确认后,写入XA对应的commitlog,然后发送xacommit'gtid'参与SET;4)如果任何一个SET返回错误,或者写入commitlog失败,则网关发送xarollback'gtid'给相关的SET,从而回滚全局事务。腾讯云DCDB的commitlog存储在SET中,这一步是分批完成的——网关后台线程会收集正在提交的分布式事务然后在一个独立的连接和事务中完成对每个SET的写入,而每个commit一个事务的日志只写入一个SET,所以这个开销不会显着增加事务的提交时间或降低TPS。而且,依托腾讯云DCDB现有的强大的同步和容灾特性,只要XA成功写入commitlog,就意味着数据已经写入slave。虽然绝大多数XA事务都可以正常执行。但是极少数的异常情况还是会影响到整个集群的稳定性。因此,腾讯云设计了一个agent(监控模块),在失败后继续协助提交本地MySQL上的preparedtransactions。处理还在准备中的本地交易数据;如果提交日志上没有事务提交决定,代理也会回滚超时后尚未提交的准备好的本地事务。虽然XA已经在MySQL5.5、5.6等版本实现,但这两个版本相比5.7在性能上仍有不足,所以目前腾讯云在公有云上只支持基于5.7.17的XA版本。今天,腾讯云在MySQL、percona、MariaDB等分支做了很多优化和相关bug修复(部分已提交社区补丁修复或开源)。未来,腾讯云将继续致力于新功能的开发和相关bug的修复,为众多有需求的企业提供更好的分布式数据库支持。原文链接:https://cloud.tencent.com/community/article/120564【本文为专栏作者《腾讯云技术社区》原创稿件,转载请联系原作者获得授权】点此查看更多关于作者的好文
