10 分钟看懂分布式事务

什么是分布式事务

问题的引出

先看一张图,一个电商平台的架构图。

对于用户来说的一个创建订单的过程,背后很可能跨越了多个应用服务。涉及诸如:订单、库存、积分、优惠券等多个微服务模块,而每个模块的数据库可能存在不同节点上,但是其中的任何一个环节都有可能程序运行错误,导致数据的不一致。

例如这个支付操作里涉及到的多个数据库。

单一数据库可以简单的使用事务来保证一致性,但是分布式的问题则需要分布式的事务来控制数据的一致性。

分布式事务的产生的原因

  • 数据库分库分表
    • 由于单表的数据量巨大导致的分库分表,则会涉及到多个数据库的一致性问题。
  • 应用SOA化
    • 业务的服务化。多个业务中心有各自的数据库,也会涉及多个数据库的一致性问题

事务的ACID特性

分布式事务本质也是一个事务,则需要满足ACID特性。

  • 原子性(A)
    • 在整个事务中的所有操作,要么全部完成,要么全部不做,没有中间状态。
  • 一致性(C)
    • 事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。
  • 隔离性(I)
    • 隔离性就是说,事务与事务之间不会互相影响,一个事务的中间状态不会被其他事务感知。
  • 持久性(D)
    • 一旦事务完成了,那么事务对数据所做的变更就完全保存在了数据库中,即使发生停电,系统宕机也是如此。

常见的分布式事务解决方案

两阶段提交--XA提交机制

  • XA中大致分为两部分:
    • 事务管理器:作为全局的调度者,负责各个本地资源的提交和回滚
    • 本地资源管理器:往往由数据库实现
  • XA机制将提交过程两个阶段
    • prepare
    • commit
流程:
  1. 事务管理模块在prepare服务A的DB事务、服务B的DB事务都成功后。
  2. 逐个commit这些DB事务。

DB在prepare返回OK后,如果没有收到来自事务管理模块的commit/rollback请求则会一直保留该分支事务的数据。

出现错误的情况:
  • 若在prepare阶段出现故障,则回滚prepare过的分支事务,从而达到全局事务回滚。
  • 若在commit阶段出现故障,后续仍然可以再次commit那些未成功commit的分支事务,最终达到全局事务提交。
优点缺点
  • 优点:实现简单易懂
  • 缺点:性能不理想,高并发场景下表现不佳

消息事务+最终一致性

流程

借助消息队列,在处理业务逻辑的地方,发送消息,业务逻辑处理成功后,提交消息,确保消息是发送成功的。成功后的消息去通知下一步操作的B系统服务,直到全部执行完毕。

出现错误的情况:
  • 通过消息队列投递来进行处理,如果成功,则结束,如果没有成功,则重试,直到成功。
  • 但是注意要做到幂等性控制,因为在系统调用没有达到期望的结果后会重试,不然就会出现重复的问题。
优点缺点
  • 优点:实现和逻辑简单易懂,性能大幅度提升。
  • 缺点:牺牲了一定的一致性,效果是最终一致性的。

三阶段提交--TCC(Try-Confirm-Cancel)机制

流程:
  1. 事务管理模块是在服务A、服务B执行完毕后即刻提交其参与的DB事务。
    • 如果全局事务决定提交,则逐个调用服务A和服务B的confirm逻辑
    • 如果全局事务决定回滚,则逐个调用服务A和服务B的cancel逻辑。
出现错误的情况:
  • 只需要根据全局事务当前状态,将服务A、服务B相应的confirm/cancel逻辑重新调用即可。
  • 但是,confirm/cancel逻辑可能会被多次调用,因此,需要保证其幂等性。
优点缺点
  • 优点:完全控制粒度
  • 缺点:不同的业务场景所写的代码都不一样,复用性较差。

参考资料

  1. 分布式最终一致方案梳理,Bright Moon ‘ s Blog,https://www.cnblogs.com/BrightMoon/p/5622618.html
  2. 深入理解分布式事务,高并发下分布式事务的解决方案,minesong,https://blog.csdn.net/minesong/article/details/64118963
  3. 分布式服务的事务如何处理? - bytefox的回答 - 知乎, https://www.zhihu.com/question/29483490/answer/237665712

原文发布于微信公众号 - 林欣哲(gh_aba6caba3ac7)

原文发表时间:2018-04-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java相关

java中缓存分类总结

在平时的开发中会经常用到缓存,比如locache、redis等,但一直没有对缓存有过比较全面的总结。下面从什么是缓存、为什么使用缓存、缓存的分类以及对每种缓存的...

4142
来自专栏分享达人秀

开发IDE大升级,终于迎来了Android Studio

通过前面几期的学习,我们知道了Android的前世今生,也了解了Android的系统架构和应用组件,也连续用了几期来学习Android开发环境的搭建,不...

24710
来自专栏Java架构师学习

日志: 分布式系统的核心日志的应用

最近这段时间一直在研究消息队列、文件系统、数据库等,慢慢的发现他们都有一个核心组件:日志.有时也叫write-ahead logs 、commit logs 或...

3257
来自专栏PHP在线

web缓存的作用和类型

前言&摘要 这段时间的工作内容主要是为一个客户端类型的产品增加文档在线存储和文档在线预览相关特性。由于测试的同事比较细心和专业,发现了项目实现中一些效 率低下的...

3505
来自专栏北京马哥教育

【Django新人必看】Django安装及搭建开发环境实战细解

开笔有话说 接触django有一段时间了,发现国内网站上的django学习资料,虽然有不少,但大多有老旧的通病,所基于的版本简直是太旧了,就拿《the djan...

44112
来自专栏韩伟的专栏

高性能服务器架构思路( 五 ) : 分布式缓存

在高性能的服务器架构中,常用的缓存和分布两种策略,往往是结合到一起使用的。只有清楚的理解这些技术的原理,并且和实际的业务场景结合起来,才能真正的做出满足应用要求...

3.7K0
来自专栏后端技术探索

Nginx 负载均衡实现解读

负载均衡在服务端开发中算是一个比较重要的特性。因为Nginx除了作为常规的Web服务器外,还会被大规模的用于反向代理前端,因为Nginx的异步框架可以处理很大的...

1573
来自专栏芋道源码1024

缓存穿透、缓存并发、缓存失效之思路变迁

来源:https://www.jianshu.com/p/d96906140199

1202
来自专栏YouMeek

一个Java程序员眼中的Mac OS(系列五:包管理工具)

本文初衷 整理自己脑袋中、收藏中的那些资料,来一次清空,让自己重新开始。 帮助 Mac 后来者,减少他/她入门成本 先总结 有 Homebrew 配置,安装/维...

6899
来自专栏微服务生态

缓存穿透、缓存并发、缓存失效之思路变迁

我们在用缓存的时候,不管是Redis或者Memcached,基本上会通用遇到以下三个问题:

1464

扫码关注云+社区

领取腾讯云代金券