1.传统事务
传统事务遵循ACID原则,即原子性、一致性、隔离性和持久性。
- 原子性:事务是包含一系列操作的原子操作,事务的原子性确保这些操作全部完成或者全部失败。
- 一致性:事务执行的结果必须使数据库从不一致性状态转为一致性状态。保证数据库的一致性指在事务完成时,必须使所有数据都有一致的状态。
- 隔离性:因为可能在相同的数据集上同时有许多事务要处理,所以每个事务都应该与其他事务隔离,避免数据被破坏。
- 持久性:一旦事务完成,其结果就应该能够承受任何系统的错误,比如在事务提交过程中服务器的电源被切断等。在通常情况下,事务的结果被写入持续性存储中。
2.柔性事务
在分布式数据库领域,基于CAP理论及BASE理论,阿里巴巴提出了柔 性 事 务 的 概 念 。 BASE 理 论 是 CAP 理 论 的 延 伸 , 包 括 基 本 可 用 (Basically Available)、柔性状态(Soft State)、最终一致性(Eventual Consistency)三个原则,并基于这三个原则设计出了柔性事务。
我们通常所说的柔性事务分为:两阶段型、补偿型、异步确保型、最大努力通知型。
两阶段型事务指分布式事务的两阶段提交,对应技术上的XA和JTA/JTS,是分布式环境下事务处理的典型模式。
TCC型事务(Try、Confirm、Cancel)为补偿型事务,是一种基于补偿的事务处理模型。如图 7-10所示,服务器A发起事务,服务器B参与事务,如果服务器A的事务和服务器B的事务都顺利执行完成并提交,则整个事务执行完成。但是,如果事务B执行失败,事务B本身就回滚,这时事务A已被提交,所以需要执行一个补偿操作,将已经提交的事务A执行的操作进行反操作,恢复到未执行前事务A的状态。需要注意的是,发起提交的一般是主业务服务,而状态补偿的一般是业务活动管理者,因为活动日志被存储在业务活动管理中,补偿需要依靠日志进行恢复。TCC事务模型牺牲了一定的隔离性和一致性,但是提高了事务的可用性。
异步确保型事务指将一系列同步的事务操作修改为基于消息队列异步执行的操作,来避免分布式事务中同步阻塞带来的数据操作性能下降。如图 7-11所示,在写业务数据A触发后将执行以下流程。
- 业务A的模块在数据库A上执行数据更新操作。
- 业务A调用写消息数据模块。
- 写消息日志模块将数据库的写操作状态写入数据库A中。
- 写消息日志模块将写操作日志发送给消息服务器。
- 读消息日志模块接收操作日志。
- 读消息数据调用写业务B的模块。
- 写业务B更新数据到数据库B。
- 写业务数据B的模块发送异步消息更新数据库A中的写消息日志状态,说明自己已经完成了异步数据更新操作。
最大努力通知型事务也是通过消息中间件实现的,与前面异步确保型操作不同的是:在消息由MQ服务器发送到消费者之后,允许在达到最大重试次数之后正常结束事务,因此无法保障数据的最终一致性。如下图所示,写业务数据A在更新数据库后调用写消息日志将数据操作以异步消息的形式发送给读消息日志模块;读消息日志模块在接收到数据操作后调用写业务B写数据库。和异步确保型不同的是,数据库B在写完之后将不再通知写状态到数据库A,如果因为网络或其他原因,在如图 7-12所示的第4步没有接收到消息,则消息服务器将不断重试发送消息到读消息日志,如果经过 N次重试后读消息日志还是没有接收到日志,则消息不再发送,这时会出现数据库A和数据库B数据不一致的情况。最大努力型通知事务通过消息服务使分布式事务异步解耦,并且模块简单、高效,但是牺牲了数据的一致性,在金融等对事务要求高的业务中不建议使用,但在日志记录类等对数据一致性要求不是很高的应用上执行效率很高。