分布式事务那些事

Posted chen陈序猿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分布式事务那些事相关的知识,希望对你有一定的参考价值。

最近打算在年底完成的两个框架是分布式事务框架,意在解决分布式环境下的数据一致性,所以今天想聊聊分布式事务的那些事。



什么是事务

事务大家都很好理解。就是关系型数据库和部分非关系型数据库(如新版本Mongo)对应用提供的来保证数据强一致性的ACID特性。在一个业务的发起中,数据库能保证一个会话所提交的一系列sql操作,要么全部成功,要么全部失败。事务的特性保障了我们的业务数据可以在正确编码的正确性,所以十分重要。

在传统的单机应用时代。后台的服务架构长这样:

应用直连后台,后台直连数据库(如mysql)。

事务的声明也更简单:

在业务操作前,给mysql发送指令:begin;

业务操作完成给mysql发送指令:commit;

业务发生异常给mysql发送指令:rollback;

在一些封装度高的应用中,一个@transactional注解,搞定一切。

什么是分布式事务

随着业务的庞大和臃肿,项目的拆分和微服务化日渐有趋势。要不然维护一个巨无霸系统相当难受。微服务下,一个业务,可能是这个架构:

分布式事务那些事

service1有自己的业务数据库。但service1还是要调用service2和service3。由于三个服务使用了3个独立的数据库。并不能通过强一致的数据库层面的事务来保证数据完整性。这时候,就需要另外的事务解决方案,这就是分布式事务。

简单举个例子:假设service1调用service2,service1调用超时,回滚掉了本地的事务,但是service2实际上收到了调用请求,如果执行成功,则会出现db1 rollback,db2 commit;数据错误。

我们可以知道,在分布式环境下,网络一定要考虑成不稳定的因素。优秀的程序员一定会思考网络不稳定了事务无法完成该怎么办?

我们可以知道,根据墨菲定律,可能发生的事情就一定会发生。所以......

分布式事务在多数公司的应用现状

在大型公司:

一,编写专门的分布式事务框架,保证分布式业务的数据一致性。如阿里的GTS。

二,放弃分布式事务,70%的业务实际上并没有那么强的强一致性要求,比如业务日志,比如说论坛系统点赞,评论等。允许适度丢失。所以有些公司由于业务属性,也没有直面分布式事务。但是,和支付相关的强一致场景,就痛苦了。

在中小型公司:

一,工期追赶,压根不考虑分布式事务,实际上在业务上线以后,很多系统都是直接调用,没有完善的数据一致性检查机制。业务实际上处于数据裸奔状态。你会经常看到修数据的场景发生。修的数据就是因为业务状态不一致产生的错误数据。

这其实是一个成本取舍的问题,因为技术领导者可能会认为:网络异常是小概率事件,考虑分布式事务太复杂了,所以就修数据吧。

二,针对每一个业务场景设计很多的中间状态和幂等检查。为了保证1%的网络问题造成的数据错误,业务开发周期可能要延长两到三倍。

总结:

正所谓,软件的事,没有什么是多加一层解决不了,如果解决不了,那就再加一层。程序员要做的事情不就是不断的抽象么,于是基于业务模型之前,就有了很多的分布式事务解决方案。他们各有好坏。你看,阿里都卖起了全局事务服务:

分布式事务那些事

据笔者不怎么完善的了解,貌似GTS是要接管业务数据的数据源,整个实现修改了数据库默认的隔离级别,相当于魔改数据库。

分布式解决方案-两阶段提交

DTP模型-标准分布式事务:

分布式事务那些事

这里涉及到两个协议:

TX协议:应用与全局事务管理器交互的协议

XA协议:全局事务管理器与资源管理器的交互

两阶段提交:

事务管理器发起准备命令(第一阶段)

资源管理器去执行每个服务的数据操作,(只执行业务操作sql,但不commit,这时候,就是锁定状态)

事务管理器搜集资源管理器的执行结果,只要有一个准备阶段发生错误,则告知各个资源管理器去执行rollback,否则,commit。(第二阶段)。如下图:

分布式事务那些事

分布式事务那些事


在javaEE规范中,都有对XA模式的支持。比如,如果你看到一些jar包里部分package是以XA开头的,就是对两阶段XA事务的支持。虽然基本不会使用。

两阶段提交带来的问题:

一,全局锁LOCK掉整个大事务,性能低下,全局锁带来了极大的风险。

二,网络是不可靠的,在两阶段任务一个阶段,如果出现网络问题,则都会导致系统出现异常。

三,侵入业务比较多,比如编程需要实现XA协议等。

因此,这样的分布式事务解决方案,不仅侵入业务,而且也没有解决实质性问题,不适合使用。


现在,互联网应用的数据一致性核心解决方案,都是:补偿。

分布式解决方案-理论基础

在互联网微服务方案中,存在CAP定理和BASE理论:

BASE理论简单可以总结如下方案:

BA:Basic Availability 基本业务可用性。

S :  Soft state 软状态 允许数据短时间不同步。异步

E:Eventual consistency 最终一致性(数据最终都是一致的,你不能要求实时一致性,如果产品经理要求实时一致性,就把产品经理打屎!)


基于BASE理论:产生如下柔性事务解决方案:

可查询操作

幂等操作

TCC操作

可补偿操作


可查询操作:多用于分布式解决方案-最大努力通知型解决方案:(不同公司的系统):

比如说淘宝异步通知,只通知一定次数,通知完还收不到响应我就不通知了。但是淘宝要提供查询订单状态结果的接口,当业务方状态异常的时候来查询。这就是可查询。

幂等:网络是不可靠的,在收不到ACK的情况下,接口可能会被重复调用,因此接口要幂等。一笔订单调用多次和调用一次结局一样。

TCC和可补偿是下文要将的。分布式事务的关键就是补偿。

分布式解决方案-TCC

TCC解决方案是目前分布式事务常用解决方案之一。也是笔者近期将要实现的一个分布式事务框架rpc-tcc-transaction(敬请关注)。

TCC解决方案要求业务接口每一个业务都写三个接口:tryX,confirmX,cancelX。

try:各个业务接口预留业务资源。

confirm:try阶段没有问题,执行confirm。

cancel:try阶段发生问题,执行cancel。

成功的事务删除日志。

事务恢复:定时线程根据事务日志获取执行结果恢复事务(补偿的方式。)

和XA事务相比,优点:

1)不锁整个数据库,每个接口都是独立的事务。

2)通过补偿实现最终一致性。

3)在足够优化后性能较为可靠。

4)可以实现与业务和具体RPC框架不耦合。

缺点:

1)性能有些损耗。

2)开发成本提升。

3)业务自行实现幂等。

分布式事务那些事

分布式事务解决方案-可靠消息最终一致性

可靠消息最终一致性是最常用的一致性解决方案。

他适合实时性不那么高的一致性场景。如对账,统计。笔者今年年底要实现可靠消息最终一致性分布式事务框架message-transaction。(敬请关注)

正向流程是这样的:

分布式事务那些事

是不是很简单。但是网络是不可靠的,我们还需要逆向流程做事务补偿。

逆向流程:

上面的流程,1,2,3,4,5,6,7,都是有可能会出现问题的。

需要逆向流程:

1,消息确认,待确认的消息到底主动方到底有没有主动执行成功?

2,消息消费,长时间未消费的投递重新消费。


上面的架构看似有些和业务耦合?实际上有2个优化点:

1,与业务方1的耦合可以做标准消息服务接口和标准消息会调接口,形成规范。

2,与业务方2的耦合可以在业务方2之前挂载一个通用代理。

总结

作为一个程序员,不断思考总结行业技术痛点,才能有所进步。

上面的分布式事务解决方案不是我凭空杜撰的,而都是有相关的理论依据。

我写的分布式事务框架,可能将来在工作中,在遇到事务问题,可以直接提供解决方案,降低开发成本,保障业务强大的容错性。对于一个程序员来说,这是最具有幸福感的事情了。

欢迎留言分享自己的思考。

(完)

chen陈序猿|一起学技术吧

微信ID:echo_陈

以上是关于分布式事务那些事的主要内容,如果未能解决你的问题,请参考以下文章

聊一聊分布式事务那些事儿

聊聊分布式事务

RocketMQ——Transaction Message(事务消息)

分布式事务+DDD+负载均衡+服务治理已撸!微服务不就这点事?

那些分布式事务的经典解决方案

漫谈分布式事务的那些解决方案