问题
当我们在开发单体应用时,其实我们对事务(即 transaction)的印象并不会很深刻,一方面是大多数工程师所开发的后端应用对一致性的要求并不是很高,很多时候只是封装一层 CRUD 的 RESTful 接口,另一方面则是单体应用在面对事务需求时,处理起来十分简单直接,往往依赖于数据库提供的标准事务就可以满足我们对一致性的要求。实际上,我们最常使用的事务严格来说应该是数据库事务,即 database transaction,而大多数一致性的需求(这与并发不相关),是通过数据库事务的 ACID 特性来进行管理的,因为数据库是进行数据存储的服务,而我们只需要数据提供数据上的一致性,所以满足我们的需求。但是,本文中提到的事务,多是指广义上的计算机事务,按照 Wikipedia 的定义,应该是如下的定义:
Transaction processing is information processing in computer science that is divided into individual, indivisible operations called transactions. Each transaction must succeed or fail as a complete unit; it can never be only partially complete.
事务应是独立的、不可再分割的操作组合。每个事务中的操作必须全部成功,或者全部失败,部分成功是不允许的。事务常常用来解决系统的正确性,以及状态的一致。那么为什么我们需要在微服务的实现中强调事务的不同之处呢?原因很简单,微服务应用是由一系列的、松耦合的、独立的服务组成的应用,是没有一个中心的服务或者应用存储状态的,而数据库事务,在这个架构模式下,已经不可能满足需求。
比如我们要为用户生成订单并扣款,往往表现在代码层会是这样的情况:
- BEGIN Transaction
- 为用户创建订单,在 order 表中增加一条数据
- 修改用户的 wallet 表中的数据,进行扣款
- 联系库房,修改库存并进行发货
- Commit
大约是这样的代码:
@Transactional(rollbackFor = SomeException.class)
public BusinessResult purchase(final OrderRequest orderRequest) {
// create order
final Order order = orderService.createOrder(orderRequest);
// change the balance in consumer's wallet
walletService.minus(orderRequest.getConsumer(), order.total());
// ask inventory to reserve items
inventoryService.reserve(orderRequest.