1. 事务的概念
- 一个数据库事务通常包含对数据库进行读或写的一个操作序列。它的存在包含有以下两个目的:
- 为数据库操作提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法;
- 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互不干扰。
2. 事务特性
- 事务具有4个特性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
- 原子性:一个事务是一个不可分割的工作单元,事务中包括的诸操作要么都做,要么都不做;
- 一致性:事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性和原子性是密切相关的;
- 隔离性:一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰;
- 持久性:持久性也称永久性,指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。
- 原子性与隔离性
- 一致性与原子性是密切相关的,原子性的破坏可能导致数据库的不一致,数据的一致性问题并不都和原子性有关,因此,事务的原子性与一致性缺一不可;
- 隔离性-隔离级别
- 当多个线程都开启事务操作数据库中的数据时,数据库系统要能进行隔离操作,以保证各个线程获取数据的准确性。数据库对隔离性的级别有四个定义:脏读,不可重复读,幻读和序列化读。
- 脏读:指一个事务处理过程中读取了另一个未提交的事务中的数据。
- 不可重复读:指对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于查询间隔,数据被另一个事务修改并提交了。
- 幻读:幻读是事务非独立执行时发生的一种现象。例如事务T1对一个表中所有的行的某个数据项做了从”1“修改为”2“的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为”1“并且提交给数据库。而操作事务T1的用户如果子啊查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。
- 幻读和不可重复读都是读取了另一条已经提交的事务(这点就和脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。
3. 分布式事务
-
分布式事务理论
- 当出现一个事务要操作多个数据库的时候(分布式事务),单个数据库的ACID已经不能适应这种情况了,而在这种ACID的集群环境下,再想保证集群的ACID几乎很难达到,或者即使能达到那么效率和性能也会大幅下降,最为关键的是再很难扩展新的分区了,这时候如果再追求集群的ACID会导致我们的系统变得很差,这是我们就需要引入一个新的理论原则来适应这种集群的情况,就是CAP原则或者叫CAP定理。
- CAP定理指的是对于分布式事务,WEB服务无法同时满足以下三个属性(最多选择两个):
- C 一致性(Consistency):客户端知道一系列的操作都会同时发生(生效);
- A 可用性(Availability):每个操作都必须以可预期的响应结束;
- P 分区容错性(Partition tolerance):即使出现单个组件无法可用,操作依然可以完成。
- 具体地讲在分布式系统中,在任何数据库设计中,一个Web应用最多只能同时支持上面的两个属性。显然,任何横向扩展策略都要依赖于数据分区。因此,设计人员必须在一致性与可用性之间做出选择。
-
CAP理论
- 在分布式系统中,同时满足”CAP定律“中的“一致性”,“可用性”和“分区容错性”三者是不可能的。在互联网领域的绝大多数的场景,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证“最终一致性”,只要这个最终时间是在用户可以接受的范围内即可。
-
BASE理论
- CAP理论告诉我们,只能在C、A、P中选择两个条件。而对于业务系统而言,我们往往选择牺牲一致性来换取系统的可用性和分区容错性。它的重要程度比一致性要高,不过这里需要指出的是,所谓的“牺牲一致性”并不是完全放弃数据一致性,而是牺牲强一致性换取弱一致性。
- BASE是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网分布式系统实践的总结,是基于CAP定律逐步演化而来。其核心思想是即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。
- BA:Basic Available基本可用;整个系统在某些不可抗力的情况下,仍然能够保证“可用性”,即一定时间内仍然能够返回一个明确的结果。只不过“基本可用”和“高可用”的区别是:
- “一定时间”可以适当延长;比如当举行大促,响应时间可以适当延长;
- 给部分用户返回一个降级页面,从而缓解服务器压力。但要注意,降级页面仍然是返回明确结果。
- S:Soft State 柔性状态;同一数据的不同副本的状态,可以不需要实时一致;
- E:Eventual Consistency 最终一致性;同一数据的不同副本的状态,可以不需要实时一致,但一定要保证经过一定时间后仍然是一致的。
-
ACID能够保证事务的强一致性,即数据是实时一直的。这在本地事务中是没有问题的,在分布式事务中,强一致性会极大的影响分布式系统的性能,因此分布式系统中遵循BASE理论即可。但分布式系统的不同业务场景对一致性的要求也不同,我们需要根据具体业务场景,在ACID和BASE之间寻求平衡。
4. 分布式事务协议
- 分布式事务协议主要有三种:XA规范,两阶段提交协议 2PC,三阶段提交协议 3PC;
5. 分布式事务解决方案
- 解决方案具体有如下几种:
- 全局事务-强一致性;
- 本地消息表(异步确保)-最终一致性;
- 最大努力通知;
- TCC-最终一致性;
- MQ事务消息;
- Sagas事务模型;
- TCC(补偿事务)
- TCC其实就是采用的补偿机制,其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。它分为三个阶段:
- Try阶段主要是对业务系统做检测及资源预留;
- Confirm阶段主要是对业务系统做确认提交,Try阶段执行成功并开始执行Confirm阶段时,默认Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功;
- Cancel阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。
- 优点:跟2PC比起来,实现以及流程相对简单了一些,但数据的一致性比2PC也要差一些;
- 缺点:缺点还是比较明显的,在2,3步中都有可能失败。TCC属于应用层的一种补偿机制,所以需要程序员在实现的时候多写很多补偿的代码,在一些场景中,一些业务流程可能用TCC不太好定义及处理。
- TCC其实就是采用的补偿机制,其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。它分为三个阶段:
- 结论:分布式事务本身是一个技术难题,是没有一种完美的方案应对所有场景的,具体还是要根据业务场景去抉择。
- 选择建议
- 在面临数据一致性问题的时候,首先要从业务需求的角度出发,确定我们对于一致性模型的接受程度,再通过具体场景来决定解决方案;
- 从应用角度看,分布式事务的现实场景往往无法避免,在有能力给出其他解决方案前,2PC也是一个不错的选择;
- 对于购物转账等电商和金融业务,中间件层的2PC最大问题在于业务不可见,一旦出现不可抗力或意想不到的一致性破坏,如数据节点永久性宕机,业务难以根据2PC的日志进行补偿。金融场景下,数据一致性是命根,业务需要对数据有百分之百的掌控力,建议使用TCC这类分布式事务模型,或基于消息队列的柔性事务框架,这类两种方案都在业务层实现,业务开发者具有足够掌控力,可以结合SOA框架来架构,包括Dubbo、Spring Cloud等。
- tcc-transaction
- Try:尝试执行业务,完成所有业务检查(一致性),预留必须业务资源(准隔离性);
- Confirm:确认执行业务,真正执行业务,不作任何业务检查,只使用Try阶段预留的业务资源,Confirm操作满足幂等性;
- Cancel:取消执行业务,释放Try阶段预留的业务资源,Cancel操作满足幂等性。
- 分布式事务开源方案:tcc-transaction,hmily,EasyTransaction,LCN,Raincat,myth。