浅谈分布式事务

(转)### 什么是事务
事务(Transaction)是数据库系统中一系列操作的一个逻辑单元,所有操作要么全部成功要么全部失败。

ACID

说起事务,就不得不谈事务的四大特性ACID

  • 原子性(Atomicity)
    一个是事务的所有操作,要么全部成功,要么全部失败,不会结束在中间的某个环节。事务在执行过程中发生错误或者异常,会恢复(Rollback)到事务开始前的状态,就像这个事务没有执行过一样。比如转账要么全部成功,要么全部失败,不可能一个账号扣了钱,另一个账号没加钱,不满足原子性。
  • 一致性(Consistency)
    事务确保数据从一个valid状态转换到另一个valid状态。这里的一致性强调的是事务操作使得数据一直处于符合状态预定规则。比如转账,事务前两个账号一共1000元,转账后也必须是1000元。
  • 隔离性(Isolation)
    事务通常是并发执行的,是同时对数据库进行读写和修改的,隔离性要求多个事务并发执行对数据库的影响看起来跟串行一样。通常为了提高1并发度,我们互弱化1事务并发时对数据的一致性要求,允许若干种数据不一致的现象,这就是不同的事务隔离级别:包括读未提交(Read uncommitted)、读提交(Read committed)、可重复度(repeatable read)、串行化(Serializable)。严格来说,只有最高级别的串行化才严格符合隔离性。
  • 持久性(Durability)
    事务处理完成后,对数据的修改是永久的,及时系统出现故障也不会丢失。
    ACID都是为了保障数据的一致性,不满足ACID则可能会出现数据不一致。

分布式事务

现阶段业务发展迅猛,数据往往超出单机数据库所能处理的极限,会遇到性能的瓶颈。而应用层面微服务架构越来越流行,从原来的单体应用拆分成一个个独立的微服务,当应用通过一组微服务来协助完成时,对数据的一致性就需要分布式事务来保证。
对数据库通常采用垂直拆分和水平数据分片,将数据拆分到多个不同的数据节点上。如果一个事务涉及了多个不同分片节点则产生了分布式事务。
常见的几种分布式事务实现:

  • 基于XA协议的2pc

两阶段提交(2pc)应该属于被提到最多的分布式事务实现方案。该协议(Two-Phase-Commit)主要定义了事务管理器(Transaction Manager)和资源管理器(Resource Manager)之间的接口。
两阶段提交将提交过程分为两个阶段,在第一阶段,协调者询问所有的参与者是否可以提交事务,所有参与者向协调者投票。第二阶段,协调者根据所有参与者的投票结果做出事务可以全局提交或者回滚的决定,并通知参与者执行该决定。

  • 2pc的缺点
    2pc虽然保证了提交的原子性,但缺点也很明显:
    1、同步阻塞。执行过程中,所有参与的节点都是事务阻塞型的。当参与者占有资源时,其他第三方节点访问资源不得不处于阻塞状态。
    2、单点故障。由于协调者的重要性,一旦协调者发生故障,参与者会一直阻塞下去。尤其第二阶段,所有参与者会处于锁定事务资源的状态,从而无法继续完成其他事务操作。
    2pc的协调者和每个参与者只要有两轮消息交互,写日志等,过程又是阻塞状态,性能低下。

  • 2pc的一致性
    从隔离性的角度来说,2pc只能算是最终一致性,算不得强一致性。

  • MySQL对XA支持问题
    1、prepare未写入binlog,若主机宕机切换回来后丢失prepare
    2、客户端退出或者主机宕机,MySQL会自动那个回滚。

  • TCC

TCC事务机制相对于XA的2pc机制,其特征在于不依赖资源管理器(RM)对XA的支持,同时通过对业务逻辑的调度来实现分布式事务。
TCC型事务(Trying/Confirming/Canceling)

  • TRYING阶段主要是对业务系统做检测及资源预留。
  • CONFIRMING阶段主要是对业务系统做确认提交,TRING阶段执行成功并开始执行CONFIRMING阶段时,默认是一定成功的,即:TRING成功,CONFIRMING成功。
  • CANCELING阶段主要是在业务执行阶段执行错误,需要回滚的状态下执行的业务取消和预留资源的释放
  • TCC和2pc的区别

2pc的一个完成的事务生命周期:begin->业务逻辑->prepare->commit。TCC的一个完整的事务生命周期:begin->业务逻辑(try业务)->commit(confirm业务)。
TCC的Tring/Confirming/Canceling三个接口针对每个事物都需要用户自己来实现,对用户不太友好,增加开发工作量。

  • SAGA

SAGA的核心思想是将分布式事务分成多个本地事务,即主事务和从事务。本地事务·先提交,然后通过消息通知从事务,从事务从消息中获取信息进行本地提交。这是一种异步提交机制,只能保证最终一致性,但可用性高,不会因为故障而阻塞。
但实际上并没有解决分布式问题。为了使第一个事务部涉及分布式操作,消息队列必须与第一个事务使用一套存储资源,同理为了使第二个事务是本地的,又需要和第二个事务存储在一起,这样本质上没有规避分布式事务。

  • 最大努力提交

1、与2pc相比,省去prepare,本质上属于1pc
2、commit推迟到最后一步执行
优点性能非常好,且对用户透明,缺点是可能存在部分提交成功部分失败的情况。而且对于已经成功的commit无法rollback。但是由于将相对容易出错的sql执行阶段先执行,commit推迟到最后一起执行,相当于将可能出错的窗口缩小到最后的commit阶段,而commit之前的出错可以正常回滚。
该模型适合绝大多数不涉及金钱来往的业务,在性能和一致性之间有一个较好的平衡。

你可能感兴趣的:(浅谈分布式事务)