saga一般有“一连串的事件(或经历)”的意思,下文译为“事件履历”,有不对的地方,请指出。
场景
当已经应用每个服务一个数据库模式时,每个服务有自己的数据库。然而某些事务跨多个服务,因此需要一套机制来确保服务间的数据一致性。例如,设想正在构建一个电子商务商店,用户在该商店有一个信用额度限制。该应用(电子商务商店)必须保证一个新的订单不会超出用户信用额度限制。因为订单和用户在不同的数据库中,应用不能够简单的使用本地ACID事务。
问题
如何在服务之间维护数据一致性?
约束条件
2PC不是选项。
解决方案
实现每个跨多个服务的事务为一个事件履历。一个事件履历(saga)是指一连串的本地事务。在事件履历中,每个本地事务更新数据库并且发布一个消息或事件来触发下一个本地事务。如果某个本地事务失败了,是因为它违反了某个业务规则,那么某个事件履历将会执行一系列的取消之前本地事务做的修改的补偿事务。
实例
使用该方式的某个电子商务应用会使用一个由下面本地事务组成的事件履历来创建一个订单:
1. 订单服务创建一个待定(pending)状态的订单。
2. 用户服务尝试为该订单预留信用额度。
3. 订单服务更改订单状态为要么批准(approved),要么取消(cancelled)。
每个本地事务发布一个事件或学习都会触发下一步。例如,在创建订单事件履历中,订单服务发布一个订单创建事件并且用户服务要么发布一个信用额度预留事件,要么发布一个超出信用额度限制事件。
影响
该模式有如下的好处:
能够使应用在多个服务之间不使用分布式事务来维护数据一致性。
该模式有如下的弊端:
编程模型很复杂。例如,开发人员必须设计补偿事务用来显式地撤销在某个早前事务履历中的更改。
需要注意的问题:
为了可靠性,服务必须以原子方式更新数据库和发布事件。服务不能够使用跨数据库和消息代理的分布式事务的传统机制,作为替代,服务必须使用下面列出的某个模式:
(下面的模式可以已原子方式更新状态和发布事件)
事件溯源(Event sourcing)
应用事件(Application events)
数据库触发器(Database triggers)
事务日志跟踪(Transaction log tailing)
文章来源:Pattern: Saga