参照事务的基本特性,分析基于消息系统模型之最大努力通知模型。
1.事务的特性
- A(Atomicity):事务中的全部操作都是一个原子操作序列,要么一起成功,要么一起失败。其中任何一个操作失败,之前已经成功操作也会回滚到操作之前的状态。
- C(Consistency):事务的执行结果从一个状态切换到另一个状态,当事务完成后各操作结果的状态都是操作成功的状态或操作之前的状态时,就可以说是满足一致性。
- I(Isolation):事务之间不会互相影响,各事务之间都有独立完整的数据空间。
- D(Durability):事务一旦提交,对数据的变更必须永久的保存下来,就算重启也可以恢复。
2.最大努力通知型
- 特点:不同系统间的通信或消息中间件不保证消息的正确接收/投递。
- 优点:
- 事务本身逻辑简单、实现简单。
- 因不需要保证消息的可靠,因此全流程几乎不需要阻塞、确认等额外操作。
- 缺点:
- 为了实现事务的一致性,必须另外实现一套独立的可行的校对系统。
- 因极端情况下依赖重试逻辑达到最终一致性,因此适合对于时间敏感度较低的场景。
- 只支持纯异步场景,无法处理同步的请求。(依赖额外的校对系统/重试/主动查询机制)
3.基本模型
4.分析
- 为什么需要额外的校对系统?
- 如图中第一步操作失败。服务A事务已经执行,服务B并没有执行事务。此时是不符合一致性原则的。因此需要一个额外的校对系统进行不断的轮询,补全事务流程或通知人工处理。
- 为什么需要主动查询机制?
- 如图中第二步操作失败。服务A的事务已经执行,服务B并没有执行事务。此时也不符合一致性原则。当然可以全部依赖校对系统进行校对。
- 第三步ack的时机
- ACK这个步骤是必须的,因为ACK的步骤是停止消息系统重试步骤的重要依据之一。(另一种重试机制停止可以为到达一个重试最大次数)
- 服务B接口的幂等性
- 因为在第三步收到ACK之前,消息系统会默认消息丢失,不断进行重试,因此服务必须实现幂等性。即多次调用和一次调用结果是相同的。实现方式可以通过一个唯一的事件ID或MessageID实现。
- 常见的实现场景
- 例如支付宝、微信等第三方支付的回调,前端用户点击下单后,后端生成第三方支付需要的订单信息返回前端,前端唤醒第三方APP进行支付,支付完成后第三方支付会通过之前注册好的回调,不断的尝试回调,直到我们某一次处理返回成功。该场景下一般后端也会执行一个主动查询脚本作为兜底方案。