柔性事务知足BASE理论(基本可用,最终一致)。mysql
刚性事务知足ACID理论。sql
在分布式事务当中主要讨论的是柔性事务的处理方式。数据库
柔性事务分为:服务器
两阶段提交(2-Phase Commit, 2PC)是一种比较简单的分布式一致性协议。网络
2PC协议中,每一个事务须要一个协调者来协调各个参与者。每一个事务分为两步执行。分布式
2PC是一种简单的一致性协议,它存在一些问题:优化
参与者在完成阶段一的事务执行后等待协调者的下一个请求,若协调者超时则能够自行放弃事务。日志
这种方案仍然有没法保证一致性的缺点,但并不会出现某些资料所述一直锁定资源,没法继续的状况。code
三阶段提交协议(3-Phase Commit, 3PC)进一步将事务请求分为两个阶段,能够解决2PC协议阻塞的问题但没法解决单点服务和不一致的问题。blog
3PC协议下事务分三步提交:
三阶段提交协议在CanCommit阶段不锁定资源,解决了阻塞下降吞吐量的问题。
若某个参与者进入 PreCommit 后始终未收到协调者的进一步指令则会自动提交,该策略必定程度上避免协调者单点服务问题。
可是 3PC 仍然没法解决数据不一致问题。
TCC型事务(Try/Confirm/Cancel)能够归为补偿型。补偿型的例子,在一个长事务( long-running )中 ,一个由两台服务器一块儿参与的事务,服务器A发起事务,服务器B参与事务,B的事务须要人工参与,因此处理时间可能很长。若是按照ACID的原则,要保持事务的隔离性、一致性,服务器A中发起的事务中使用到的事务资源将会被锁定,不容许其余应用访问到事务过程当中的中间结果,直到整个事务被提交或者回滚。这就形成事务A中的资源被长时间锁定,系统的可用性将不可接受。
WS-BusinessActivity提供了一种基于补偿的long-running的事务处理模型。仍是上面的例子,服务器A的事务若是执行顺利,那么事务A就先行提交,若是事务B也执行顺利,则事务B也提交,整个事务就算完成。可是若是事务B执行失败,事务B自己回滚,这时事务A已经被提交,因此须要执行一个补偿操做,将已经提交的事务A执行的操做做反操做,恢复到未执行前事务A的状态。这样的SAGA事务模型,是牺牲了必定的隔离性和一致性的,可是提升了long-running事务的可用性。
TCC 将事务提交分为 Try - Confirm - Cancel 3个操做。
TCC优势:让应用本身定义数据库操做的粒度,使得下降锁冲突、提升吞吐量成为可能。
TCC不足之处:
流程:
try
给全部参与者try
, 尝试预留资源, 并返回给发起者commit
/cancel
指令给参与者commit
/cancel
, 并返回执行结果例子:
购买从 广州到北京的机票, 由于购买不到直达的机票, 因此购买 广州->上海->北京, 在上海中转
广州->上海 南航
上海->北京 东航
由于不属于同一个航空公司, 因此须要分别购买
若是订票系统依次购买, 可能存在第一家购买成功, 第二家购买失败, 这事不能接受的
因此订票系统先向两家航空公司发送请求, 肯定是否有足够的余票, 并让对方预留票
与 2PC 的比较
TCC | 2PC | |
---|---|---|
第一阶段 | Try: 请求原业务方预留资源 | Prepare: 询问是否能够进行提交 |
段二阶段(成功) | Confirm:确认执行 | Commit: 提交事务 |
第二阶段(失败) | Cancel: 取消执行资源操做 | Rollback: 回滚事务 |
2PC 是资源层面的, 基于数据库底层 (好比mysql的xa事务), 开发者不可感知, 无侵入性
TCC 是业务层面, 开发者可感知, 能够根据业务对事务作特定的优化
存在的问题
存在和 2PC 相似的问题
若是发起者发送 confirm
过程失败, 致使有的参与者接收到指令, 执行了comfirm
而有的参与者因为没有接收到指令, 而由于timeout
, 执行了cancel
破坏了整个系统的数据一致性
背景:
一直以来, 执行数据库事务都是使用 LLT (long lived transaction), 即跨越多个数据库事务的事务, 一次性完成全部事务, 其中不容许其余事务打断, 使用这种机制, 能够保证数据库的数据一致性
可是会带来几个问题:
简述
而 Saga 模式是为了弥补 LLT 的缺陷
Saga 模式将一个长事务分割多个子事务 (saga), 而后逐一执行每个子事务, 一旦其中一环出现了错误, 经过补偿机制, 一一回滚以前已经执行的事务
$$
T1 T2 T3...Tj...Tn\
transaction\
C1 C2 C3...Cj...Cn \
compensating transaction
$$
整个流程有如下状况:
$$
T1 → T2 → T3 →...→...→ Tn
$$
$$
T1 → T2 → T3 →...→...→ Tj → Cj →...→ C3 → C2 → C1
$$
注意点:
例子
假设一我的须要进行如上的飞机票预订, 订票系统须要向四个航空公司发出订票请求
若是其中任何一个环节出现了问题, 就经过补偿机制, 将以前预订的票逐一退订
与TCC的比较
try
接口, 只须要能够commit
和rollback