分布式事务

什么是事务?

发生错误,回滚操作。
要么全部正确执行,要么全不执行。

事务四大特性

ACID 原子性Atomicity,一致性Consistency,隔离性Isolation,持久性Durability

  • 原子性:事务里是一个不可分割整体,要么一起执行,要么一起不执行。
  • 一致性:事务执行前后,数据库一致性没有被破坏。提交事务没有中间状态。要么提交前,要么提交后。
  • 隔离性:事务之间互不干扰。
  • 持久性:提交了就永久改变了,不会不生效。

事务隔离级别


读未提交 read-uncommitted
  • A还没提交,B就读了。若A rollback,B读到错误数据(脏读)。
不可重复读/读提交 read-committed
  • 提交了才能读
  • A读,B修改并提交,A再读变了(不可重复读)
可重复读 repeatable-read
  • 读时不可修改(行锁)A读,B不准改,A再读完成,B改
  • A读(范围),B插入并提交(不修改A锁的),A再读,个数变了(幻读)
串行化/可 serializable
  • 读时不可增删改(表锁)
事务隔离级别 脏读 不可重复读 幻读
读未提交(read-uncommitted)
不可重复读(read-committed)
可重复读(repeatable-read)
串行化(serializable)

级别越高,执行效率就越低。

  • MySQL默认可重复读
  • Oracle默认读提交,支持read committed 和 serializable。另外还支持read only(只读,不可修改) 和 read write(默认)

事务传播级别

7种:

传播级别 描述 上下文存在事务 上下文不存在事务
REQUIRED 默认 加入事务中 新建事务
SUPPORTS 支持 加入事务中 非事务方式执行
MANDATORY 强制上下文有事务 加入事务 抛出异常
REQUIRES_NEW 新事务 新建事务,挂起上下文事务 新建事务
NOT_SUPPORTED 不支持 挂起上下文事务,执行当前逻辑 新建事务
NEVER 不可有上下文事务 抛出runtime异常,强制停止 非事务方式执行
NESTED 嵌套执行 子回滚,父不影响;父回滚,子回滚;子先提交,父后提交 新建事务

一致性解决方案

两阶段提交(2PC),三阶段提交(3PC),补偿事务(TCC),消息中间件(MQ异步确保)& 最大努力通知(定期校对)

两阶段提交(2PC)

Prepare、Commit 两个阶段

准备阶段

1)协调者节点向所有参与者节点询问是否可以执行提交操作(vote),并开始等待各参与者节点的响应。
2)参与者节点执行询问发起为止的所有事务操作,并将Undo信息和Redo信息写入日志。(注意:若成功这里其实每个参与者已经执行了事务操作)
3)各参与者节点响应协调者节点发起的询问。如果参与者节点的事务操作实际执行成功,则它返
回一个”同意”消息;如果参与者节点的事务操作实际执行失败,则它返回一个”中止”消息。

提交阶段
  • 当协调者节点从所有参与者节点获得的相应消息都为”同意”时:
    1)协调者节点向所有参与者节点发出”正式提交(commit)”的请求。
    2)参与者节点正式完成操作,并释放在整个事务期间内占用的资源。
    3)参与者节点向协调者节点发送”完成”消息。
    4)协调者节点受到所有参与者节点反馈的”完成”消息后,完成事务。

  • 如果任一参与者节点在第一阶段返回的响应消息为”中止”,或者 协调者节点在第一阶段的询问超时之前无法获取所有参与者节点的响应消息时:
    1)协调者节点向所有参与者节点发出”回滚操作(rollback)”的请求。
    2)参与者节点利用之前写入的Undo信息执行回滚,并释放在整个事务期间内占用的资源。
    3)参与者节点向协调者节点发送”回滚完成”消息。
    4)协调者节点受到所有参与者节点反馈的”回滚完成”消息后,取消事务。

2PC缺点:
  1. 同步阻塞问题。执行过程中,所有参与节点都是事务阻塞型的。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。
  2. 单点故障。由于协调者的重要性,一旦协调者发生故障。参与者会一直阻塞下去。尤其在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。(如果是协调者挂掉,可以重新选举一个协调者,但是无法解决因为协调者宕机导致的参与者处于阻塞状态的问题)
  3. 数据不一致。在二阶段提交的阶段二中,当协调者向参与者发送commit请求之后,发生了局部网络异常或者在发送commit请求过程中协调者发生了故障,这回导致只有一部分参与者接受到了commit请求。而在这部分参与者接到commit请求之后就会执行commit操作。但是其他部分未接到commit请求的机器则无法执行事务提交。于是整个分布式系统便出现了数据部一致性的现象。
  4. 二阶段无法解决的问题:协调者再发出commit消息之后宕机,而唯一接收到这条消息的参与者同时也宕机了。那么即使协调者通过选举协议产生了新的协调者,这条事务的状态也是不确定的,没人知道事务是否被已经提交。

三阶段提交(3PC)

CanCommit、PreCommit、DoCommit三个阶段

  1. 引入超时机制。同时在协调者和参与者中都引入超时机制。
  2. 在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。
CanCommit阶段

协调者向参与者发送commit请求,参与者如果可以提交就返回Yes响应,否则返回No响应。

  1. 事务询问 协调者向参与者发送CanCommit请求。询问是否可以执行事务提交操作。然后开始等待参与者的响应。

  2. 响应反馈 参与者接到CanCommit请求之后,正常情况下,如果其自身认为可以顺利执行事务,则返回Yes响应,并进入预备状态。否则反馈No

PreCommit阶段
  • 假如协调者从所有的参与者获得的反馈都是Yes响应,那么就会执行事务的预执行。
  1. 发送预提交请求 协调者向参与者发送PreCommit请求,并进入Prepared阶段。
  2. 事务预提交 参与者接收到PreCommit请求后,会执行事务操作,并将undo和redo信息记录到事务日志中。
  3. 响应反馈 如果参与者成功的执行了事务操作,则返回ACK响应,同时开始等待最终指令。
  • 假如有任何一个参与者向协调者发送了No响应,或者等待超时之后,协调者都没有接到参与者的响应,那么就执行事务的中断。
  1. 发送中断请求 协调者向所有参与者发送abort请求。
  2. 中断事务 参与者收到来自协调者的abort请求之后(或超时之后,仍未收到协调者的请求),执行事务的中断。

相对于2PC,3PC主要解决的单点故障问题,并减少阻塞,因为一旦参与者无法及时收到来自协调者的信息之后,他会默认执行commit。而不会一直持有事务资源并处于阻塞状态。但是这种机制也会导致数据一致性问题,因为,由于网络原因,协调者发送的abort响应没有及时被参与者接收到,那么参与者在等待超时之后执行了commit操作。这样就和其他接到abort命令并执行回滚的参与者之间存在数据不一致的情况。


补偿事务(TCC)

基于业务层面的事务定义。
锁粒度完全由业务自己控制。
本质是一种补偿的思路。
把事务运行过程分成 Try、Confirm / Cancel 两个阶段

Try :尝试执行业务
  • 完成所有业务检查( 一致性 )
  • 预留必须业务资源( 准隔离性 )
Confirm / Cancel 阶段:
  • Confirm :
    真正执行业务
    不做任务业务检查
    Confirm 操作满足幂等性
  • Cancel :
    释放 Try 阶段预留的业务资源
    Cancel 操作满足幂等性
    Confirm 与 Cancel 互斥

本地消息表

将需要分布式处理的任务通过消息日志的方式来异步执行。消息日志可以存储到本地文本、数据库或消息队列,再通过业务规则自动或人工发起重试。
本地消息表记录状态,定时扫描,重新发送失败的消息


消息中间件(MQ异步确保) 最大努力通知(定期校对)

RocketMQ

  • 业务方法内要向消息队列提交两次请求,一次发送消息和一次确认消息。如果确认消息发送失败了RocketMQ会定期扫描消息集群中的事务消息,这时候发现了Prepared消息,它会向消息发送者确认,所以生产方需要实现一个check接口,RocketMQ会根据发送端设置的策略来决定是回滚还是继续发送确认消息。这样就保证了消息发送与本地事务同时成功或同时失败。

  • 系统A除了实现正常的业务流程外,还需提供一个事务询问的接口,供消息中间件调用。当消息中间件收到一条事务型消息后便开始计时,如果到了超时时间也没收到系统A发来的Commit或Rollback指令的话,就会主动调用系统A提供的事务询问接口询问该系统目前的状态。该接口会返回三种结果:
    提交:将该消息投递给系统B。
    回滚:直接将条消息丢弃。
    处理中:继续等待。


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339

推荐阅读更多精彩内容