php数据库分布式事务 php 分布式( 二 )


总的来说 , XA协议比较简单,而且一旦商业数据库实现了XA协议,使用分布式事务的成本也比较低 。但是,XA也有致命的缺点,那就是性能不理想 , 特别是在交易下单链路,往往并发量很高,XA无法满足高并发场景 。XA目前在商业数据库支持的比较理想,在mysql数据库中支持的不太理想,mysql的XA实现,没有记录prepare阶段日志,主备切换回导致主库与备库数据不一致 。许多nosql也没有支持XA,这让XA的应用场景变得非常狭隘 。
5.2、消息事务+最终一致性
所谓的消息事务就是基于消息中间件的两阶段提交 , 本质上是对消息中间件的一种特殊利用 , 它是将本地事务和发消息放在了一个分布式事务里,保证要么本地操作成功成功并且对外发消息成功,要么两者都失败 , 开源的RocketMQ就支持这一特性 , 具体原理如下:
1、A系统向消息中间件发送一条预备消息
2、消息中间件保存预备消息并返回成功
3、A执行本地事务
4、A发送提交消息给消息中间件
通过以上4步完成了一个消息事务 。对于以上的4个步骤,每个步骤都可能产生错误,下面一一分析:
步骤一出错,则整个事务失败,不会执行A的本地操作步骤二出错,则整个事务失败,不会执行A的本地操作步骤三出错,这时候需要回滚预备消息 , 怎么回滚php数据库分布式事务?答案是A系统实现一个消息中间件的回调接口 , 消息中间件会去不断执行回调接口,检查A事务执行是否执行成功,如果失败则回滚预备消息步骤四出错,这时候A的本地事务是成功的 , 那么消息中间件要回滚A吗php数据库分布式事务?答案是不需要,其实通过回调接口,消息中间件能够检查到A执行成功了,这时候其实不需要A发提交消息了,消息中间件可以自己对消息进行提交 , 从而完成整个消息事务基于消息中间件的两阶段提交往往用在高并发场景下,将一个分布式事务拆成一个消息事务(A系统的本地操作+发消息)+B系统的本地操作 , 其中B系统的操作由消息驱动,只要消息事务成功,那么A操作一定成功,消息也一定发出来了 , 这时候B会收到消息去执行本地操作,如果本地操作失败,消息会重投,直到B操作成功 , 这样就变相地实现了A与B的分布式事务 。原理如下:
虽然上面的方案能够完成A和B的操作,但是A和B并不是严格一致的,而是最终一致的 , 我们在这里牺牲了一致性,换来了性能的大幅度提升 。当然,这种玩法也是有风险的,如果B一直执行不成功,那么一致性会被破坏,具体要不要玩 , 还是得看业务能够承担多少风险 。
5.3、TCC编程模式
所谓的TCC编程模式,也是两阶段提交的一个变种 。TCC提供了一个编程框架,将整个业务逻辑分为三块:Try、Confirm和Cancel三个操作 。以在线下单为例 , Try阶段会去扣库存,Confirm阶段则是去更新订单状态,如果更新订单失败,则进入Cancel阶段,会去恢复库存 。总之,TCC就是通过代码人为实现了两阶段提交,不同的业务场景所写的代码都不一样 , 复杂度也不一样,因此,这种模式并不能很好地被复用 。
6、总结
分布式事务,本质上是对多个数据库的事务进行统一控制,按照控制力度可以分为:不控制、部分控制和完全控制 。不控制就是不引入分布式事务,部分控制就是各种变种的两阶段提交,包括上面提到的消息事务+最终一致性、TCC模式,而完全控制就是完全实现两阶段提交 。部分控制的好处是并发量和性能很好,缺点是数据一致性减弱了,完全控制则是牺牲了性能 , 保障了一致性,具体用哪种方式,最终还是取决于业务场景 。作为技术人员 , 一定不能忘了技术是为业务服务的,不要为了技术而技术,针对不同业务进行技术选型也是一种很重要的能力