事务(Transaction)是做什么的?
事务存在的意义是为了保证系统中所有的数据都是符合期望的,且相互关联的数据之间不会产生矛盾[1]
要达成数据一致性(Consistency)的目标,需要三个方面来保障:
- 原子性(Atomic):在同一项业务处理过程中,事务保证了对多个数据的修改,要么同时成功,要么同时被撤销,不能只执行其中的一部分操作
- 隔离性(Isolation):在不同的业务处理过程中,事务保证了各自业务正在读、写的数据互相独立,不会彼此影响
- 持久性(Durability):事务应当保证所有成功被提交的数据修改都能够正确地被持久化,不丢失数据
根据不同的使用场景,事务可以分为本地事务、全局事务、共享事务和分布式事务。 那我们今天主要探讨的是分布式事务,所以对其他类型不做过多阐述
以下是我针对事务内容的整体架构图,可以理清思路
分布式事务
随着互联网的发展,从之前的单一项目逐渐向分布式服务做转换,现如今微服务在各个公司已经普遍存在,而当时的本地事务已经无法满足分布式应用的要求。 分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理者分别位于不同的分布式系统的不同节点之上,且属于不同的应用,分布式事务要保证在不同服务器上数据库数据的一致性。[2]
分布式事务有以下几种主要的解决方案:
CP架构解决方案:
2PC (Two-Phase Commit)
两个阶段:
prepare阶段
commit阶段
两个角色:
协调者Coordinator
参与者Participant
问题:单点故障、阻塞
3PC
三个阶段:
CanCommit
PreCommit
DoCommit
优点:引入超时机制,解决单点故障引起的事务阻塞
缺点:DoCommit阶段是超时后就会自动提交事务,但这里面其实会有一些偏差,会导致数据不一致
AP架构解决方案:
TCC (Try-Confirm-Cancel)
三个阶段:
创建事务之后
- Try:尝试执行阶段
完成所有业务可执行性的检查(保障一致性),并且预留好全部需要用到的业务资源,比如【账户余额的100元/仓库图书1本】(保障隔离性) - Confirm:确认执行阶段
不进行任何业务检查,直接使用Try阶段准备的资源来完成业务处理 - Cancel:取消执行阶段
如果任意一个业务超时或者别的原因不可行,释放Try阶段预留的业务资源,也就是进行了失败回滚
三个阶段都是独立的子事务,不会像2PC一样阻塞等待别的业务的响应
TCC位于用户代码层面,通过对业务逻辑的接口调用来实现分布式事务,拥有较高的灵活性的同时,也带来了更高的开发成本+代码入侵