## 避不开的分布式事务
https://mp.weixin.qq.com/s?__biz=MzU1MzYwMjQ5MQ==&mid=2247485412&idx=1&sn=66560e9c6f84f0d634acd35527edc70f&chksm=fbf11b30cc8692262f3c438b64bd6b6181787b7eb01b17a2d42d6859def28b10a3c683f0befb&scene=132#wechat_redirect
原创Code综艺圈[Code综艺圈](javascript:void(0);)*昨天*
收录于话题
#分布式事务1
#微服务那些事15
### 前言
关于前面系列的文章已经说到分布式服务之间的通信,则分布式事务接下来就是我们要一起学习的主题,走起。
数据库事务在现有大大小小的系统中几乎是避免不开的,或多或少总会有一些业务关联在一块;对于单机事务的应用场景和操作,相信小伙伴已经够熟练了;随着分布式、微服务的开发模式普及,分布式事务落地也成为了程序员的必备之技,接下来的几篇一起来学习和实操。
### 正文
#### 1\. 事务回顾
##### 1\. 1 事务简介
通俗一点理解就是**将一组对数据的操作(增、删、改、查)看做成一个逻辑单元,要么都执行,要么都不执行,确保数据一致性**。
##### 1.2 事务特性(ACID)
* 原子性(Atomicity)
指事务内所有操作要么一起执行成功,要么都一起失败(或者说是回滚);如事务经典转账案例:A给B转账,A把钱扣了,但B没有收到;可见这种错误是不能接受的,最终会回滚,这也是原子性的重要性。
* 一致性(Consistency)
指事务执行前后的状态一致,如事务经典转账案例:A给B互相转账,不管怎么转,最终两者钱的总和还是不变;
* 持久性(Durability)
指事务一旦提交,数据就已经永久保存了,不能再回滚;
* 隔离性(Isolation)
指多个并发事务之间的操作互不干扰,但是事务的并发可能会导致数据脏读、不可重复读、幻读问题,根据业务情况,采用事务隔离级别进行对应数据读问题处理。
##### 1.3 事务隔离级别
* 读未提交(**Read uncommitted**)
指一个事务读取到其他未提交事务的数据。可能导致数据**脏读**。
转账案例:A正在给B转账,本来转的1000,A多输入了个0,变成10000,但此事务还未提交,但此时B查询到转入的是10000,但A取消事务回滚之后,B又查询不到转入的数据。这种情况就是**脏读**
* 读已提交(**Read committed**)
指一个事务只能读取到其他事务已提交的数据,从而解决了**脏读**的问题。但可能导致数据**不可重复读**;
转账案例:A要给B转账1000,A先查看了一下余额,有1000,然后开始给B转钱,但此时A家里电费通过开启的自动缴费功能,自动从A账户扣除200缴纳电费,并提交;当A转账准备提交,再次确认余额时,钱少了200。这样就导致同一个事务中多次查询的结果不一致,这种情况就是**不可重复读**;
* 可重复读(**Repeatable read**)
指事务只要一开启,就不允许其他事务进行修改操作,从而解决了**不可重复读**问题。但可能导致数据**幻读**;
转账案例:A经常给B转账,到年底了,需要查账,然后开启了一个事务进行查询统计,刚开始查询只是10条转账记录,正准备统计时,因为紧急情况A需要给B转一笔钱应急,从而**新增**了一条新记录,并提交;而查账事务正在统计中,最后发现转账额和看到的10条转账记录不匹配。这种情况就是**幻读**
* 序列化(**Serializable**)
指事务之间只能串行话执行,就像队列一样,排队进行,这样就解决了**幻读**的问题,但是这种级别的并发性能不高,非特殊需求,这种级别一般不用。
#### 2\. 分布式事务场景
一个项目对应一个数据库,这种单机业务是平时处理的比较多的;这里主要归纳一下会出现分布式事务的场景。
##### 2.1 一个项目多个数据库
![图片](https://mmbiz.qpic.cn/mmbiz_png/qQ1zuvjsChRian5anJs8aK5dCOGQAWpFNKm6iaENbFAHnXaH1Dsz1J3kMEaIexWsFnDrZ3oWKqA1zHqcMQHuRDng/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1)
这种情况一般是并发量不大,但数据量比较大的情况,就比如一些采集设备数据做实时分析的系统,如传感器数据、电机状态等,经过一段时间,数据量会很多,导致单个数据库效率变低,所以通常会采用分业务存储。
如上图,如果出现需要操作DB1中数据的同时又需要操作DB2数据,确保两次操作要么都成功,要么都失败,这就需要事务,而这种和单一系统(一个项目,一个数据库)的事务处理方式不一样,得分布式事务进行处理。
##### 2.2 多个项目一个数据库
![图片](https://mmbiz.qpic.cn/mmbiz_png/qQ1zuvjsChRian5anJs8aK5dCOGQAWpFNf3zASGXcIVmRX93YTpiayVicX33ncGyTPAmnzbCLrRRe3GVx8YpclIQg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1)
有些系统需要将业务分开开发和部署,便于代码管理和后期维护,在数据库资源允许的情况下可以共用一个数据库,在这种情况下如果有事务操作,同样需要分布式事务进行处理。
##### 2.3 多个项目多个数据库
![图片](https://mmbiz.qpic.cn/mmbiz_png/qQ1zuvjsChRian5anJs8aK5dCOGQAWpFN1CAGZ8RGZNTlnvQRgl3XmefjiaXHHJIA8wnMcibCCYv5PicS6MoIO5smQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1)
这种方式其实就是微服务模式,分业务划分项目,每个业务对应一个数据库,这种场景下项目之间的事务肯定是分布式的啦
#### 3\. CAP了解
##### 3.1 简介
对于分布式应用场景,有很多因素是不可控的,如网络不通、设备宕机、自然灾害等原因导致服务不可用,这种情况对于分布式而言需要有一定的取舍,不能因为个别服务的不可用,导致整个系统崩掉。通常CAP理论会成为分布式指标的取舍,根据系统业务需求,满足其中两个指标即可。如下图:
![图片](https://mmbiz.qpic.cn/mmbiz_png/qQ1zuvjsChRian5anJs8aK5dCOGQAWpFN85Hfn9gQZSwWju9Iyeic5gs5wz4pWPTwwJ89rbJAPbWpHDm4VoqeZHQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1)
**CAP是Consistency(一致性)、Availability(可用性)、PartitionTolerance(分区容错性)三个词的缩写**,具体含义如下:
* **C(Consistency-一致性):是指在写操作之后,任意节点进行读取时,都能一致获取到最新的数据状态**。为了保证数据一致性,在同步数据时会对资源短时进行锁定,目的为了避免获取到老的数据,导致数据不一致情况,但这样就会导致服务在短时间内不可用。
* **A(Availability-可用性):是指发起任何操作时都可以得到响应结果,不会出现响应超时或响应错误**。就算是数据在同步过程中也要保证可用,即宁可拿到旧数据也不要报错。
* **P(PartitionTolerance-分区容错性):这里的分区是指网络分区**,通常分布式系统,各节点会部署到不同子网,由于网络具有不可控性,可能会导致节点之间的通信失败;但在设计此类系统时,应该考虑这种情况,保证提供正常的服务,这其实可以理解为平时咱们说的高可用;**这个指标是分布式系统必备的,不然就不能叫高可用系统啦**。
##### 3.2 CAP组合
其实通过上面的概述,**C(一致性)和A(可用性)是互相排斥的**,为了保证一致性,会锁定资源导致短时间不可用,而可用性的要求就是必须对操作有对应的响应结果,就算得到的数据不是最新的也行,目的是保证可用。**而P(分区容错性)是分布式系统中必备指标,所以在分布式系统中经常的组合就是CP和AP**。
* **CP:放弃可用性,注重一致性和分区容错性,其实这就是所谓的强一致性**,可能在银行跨行转账这种强一致业务场景才会用到,具体得根据业务场景做取舍。
* **AP:放弃强一致性,注重可用性和分区容错性**,这是现在绝大多数分布式业务场景的选择,只要最后能保证最终一致性(Base理论)即可。
##### 3.3 简单理解一下BASE理论
**BASE是Basically Available(基本可用),Soft State(软状态)和Eventually Consistent(最终一致性)三个短语的缩写,是对AP的一种扩展,即当出现故障时允许部分服务不可用,但要保证核心服务正常。对于数据,允许一定时间内不一致,通过中间状态(软状态)过渡,最后保证最终一致即可**。
举例说明:
**Basically Available(基本可用)**:比如一个系统注册用户成功时需要发送信息通知,允许发送信息不成功,但注册这个核心功能要保证可用。
**Soft State(软状态)**:平时见得最多的软状态有:“支付中”、“数据处理中”等,这些状态是为了满足可用性和最终一致增加的过渡状态。
**Eventually Consistent(最终一致性)**:比如在购买商品时,支付的过程中会显示“支付中”,最终会显示“支付成功”,这个时候其实就保证最终你的账户和收款账户这个事务最终一致了,这种事务可以理解为“**柔性事务**”。
#### 4\. 分布式事务常用的解决方案
* **2PC(Two-phase commit protocol)**,又称二阶段提交,是一种强一致性解决方案。对其进行补充的还有一个叫**3PC**的解决方案。
* **TCC(Try Confirm Cancel)**,补偿事务。
* **本地消息表**
* **消息事务**
* **最大努力通知**
这里先不细说,后续逐个击破,最终还是要用代码落地。
### 总结
这篇只是一个开端,主要是大概回顾一下分布式事务中常遇到的知识点,后续主要是针对各个解决方案的落地,一起撸码。
一个被程序搞丑的帅小伙,关注"Code综艺圈",和我一起学~~~
![图片](data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg== "图片")
图片
收录于话题#微服务那些事
15个
下一篇gRPC四种模式、认证和授权实战演示
文章已于2021/07/23修改
喜欢此内容的人还喜欢
[
gRPC趁现在还没大火,抢先了解一下
gRPC趁现在还没大火,抢先了解一下
...
Code综艺圈
不喜欢
不看的原因
确定
* 内容质量低
* 不看此公众号
](javascript:void(0);)[
gRPC四种模式、认证和授权实战演示
gRPC四种模式、认证和授权实战演示
...
Code综艺圈
不喜欢
不看的原因
确定
* 内容质量低
* 不看此公众号
](javascript:void(0);)[
Redis 帝国的神秘使者,竟然想改造 C 语言!
Redis 帝国的神秘使者,竟然想改造 C 语言!
...
悟空聊架构
不喜欢
不看的原因
确定
* 内容质量低
* 不看此公众号
](javascript:void(0);)
![](https://mp.weixin.qq.com/mp/qrcode?scene=10000004&size=102&__biz=MzU1MzYwMjQ5MQ==&mid=2247485412&idx=1&sn=66560e9c6f84f0d634acd35527edc70f&send_time=)
微信扫一扫
关注该公众号
- 开始
- 公益
- 更好的使用看云
- 推荐书单
- 优秀资源整理
- 技术文章写作规范
- SublimeText - 编码利器
- PSR-0/PSR-4命名标准
- php的多进程实验分析
- 高级PHP
- 进程
- 信号
- 事件
- IO模型
- 同步、异步
- socket
- Swoole
- PHP扩展
- Composer
- easyswoole
- php多线程
- 守护程序
- 文件锁
- s-socket
- aphp
- 队列&并发
- 队列
- 讲个故事
- 如何最大效率的问题
- 访问式的web服务(一)
- 访问式的web服务(二)
- 请求
- 浏览器访问阻塞问题
- Swoole
- 你必须理解的计算机核心概念 - 码农翻身
- CPU阿甘 - 码农翻身
- 异步通知,那我要怎么通知你啊?
- 实时操作系统
- 深入实时 Linux
- Redis 实现队列
- redis与队列
- 定时-时钟-阻塞
- 计算机的生命
- 多进程/多线程
- 进程通信
- 拜占庭将军问题深入探讨
- JAVA CAS原理深度分析
- 队列的思考
- 走进并发的世界
- 锁
- 事务笔记
- 并发问题带来的后果
- 为什么说乐观锁是安全的
- 内存锁与内存事务 - 刘小兵2014
- 加锁还是不加锁,这是一个问题 - 码农翻身
- 编程世界的那把锁 - 码农翻身
- 如何保证万无一失
- 传统事务与柔性事务
- 大白话搞懂什么是同步/异步/阻塞/非阻塞
- redis实现锁
- 浅谈mysql事务
- PHP异常
- php错误
- 文件加载
- 路由与伪静态
- URL模式之分析
- 字符串处理
- 正则表达式
- 数组合并与+
- 文件上传
- 常用验证与过滤
- 记录
- 趣图
- foreach需要注意的问题
- Discuz!笔记
- 程序设计思维
- 抽象与具体
- 配置
- 关于如何学习的思考
- 编程思维
- 谈编程
- 如何安全的修改对象
- 临时
- 临时笔记
- 透过问题看本质
- 程序后门
- 边界检查
- session
- 安全
- 王垠
- 第三方数据接口
- 验证码问题
- 还是少不了虚拟机
- 程序员如何谈恋爱
- 程序员为什么要一直改BUG,为什么不能一次性把代码写好?
- 碎碎念
- 算法
- 实用代码
- 相对私密与绝对私密
- 学习目标
- 随记
- 编程小知识
- foo
- 落盘
- URL编码的思考
- 字符编码
- Elasticsearch
- TCP-IP协议
- 碎碎念2
- Grafana
- EFK、ELK
- RPC
- 依赖注入
- 开发笔记
- 经纬度格式转换
- php时区问题
- 解决本地开发时调用远程AIP跨域问题
- 后期静态绑定
- 谈tp的跳转提示页面
- 无限分类问题
- 生成微缩图
- MVC名词
- MVC架构
- 也许模块不是唯一的答案
- 哈希算法
- 开发后台
- 软件设计架构
- mysql表字段设计
- 上传表如何设计
- 二开心得
- awesomes-tables
- 安全的代码部署
- 微信开发笔记
- 账户授权相关
- 小程序获取是否关注其公众号
- 支付相关
- 提交订单
- 微信支付笔记
- 支付接口笔记
- 支付中心开发
- 下单与支付
- 支付流程设计
- 订单与支付设计
- 敏感操作验证
- 排序设计
- 代码的运行环境
- 搜索关键字的显示处理
- 接口异步更新ip信息
- 图片处理
- 项目搭建
- 阅读文档的新方式
- mysql_insert_id并发问题思考
- 行锁注意事项
- 细节注意
- 如何处理用户的输入
- 不可见的字符
- 抽奖
- 时间处理
- 应用开发实战
- python 学习记录
- Scrapy 教程
- Playwright 教程
- stealth.min.js
- Selenium 教程
- requests 教程
- pyautogui 教程
- Flask 教程
- PyInstaller 教程
- 蜘蛛
- python 文档相似度验证
- thinkphp5.0数据库与模型的研究
- workerman进程管理
- workerman网络分析
- java学习记录
- docker
- 笔记
- kubernetes
- Kubernetes
- PaddlePaddle
- composer
- oneinstack
- 人工智能 AI
- 京东
- pc_detailpage_wareBusiness
- doc
- 电商网站设计
- iwebshop
- 商品规格分析
- 商品属性分析
- tpshop
- 商品规格分析
- 商品属性分析
- 电商表设计
- 设计记录
- 优惠券
- 生成唯一订单号
- 购物车技术
- 分类与类型
- 微信登录与绑定
- 京东到家库存系统架构设计
- crmeb
- 命名规范
- Nginx https配置
- 关于人工智能
- 从人的思考方式到二叉树
- 架构
- 今日有感
- 文章保存
- 安全背后: 浏览器是如何校验证书的
- 避不开的分布式事务
- devops自动化运维、部署、测试的最后一公里 —— ApiFox 云时代的接口管理工具
- 找到自己今生要做的事
- 自动化生活
- 开源与浆果
- Apifox: API 接口自动化测试指南