分布式事务解决方案
1. 两阶段提交(2PC)
2. 三阶段提交(3PC)
3. 补偿事务(TCC=Try-Confirm-Cancel)
4. 本地消息队列表(MQ)
5. Saga 事务模型(最终一致性)
分布式事务解决方案旨在确保在分布式系统中,跨多个节点或服务的事务操作要么全部成功,要么全部失败,从而保持数据的一致性和完整性。
以下是几种常见的分布式事务解决方案:
1)两阶段提交协议(2PC)
原理:
①准备阶段(Prepare Phase)
- 事务协调者(Coordinator)向所有参与者(Participant)发送准备提交(Prepare)请求。
- 参与者执行本地事务,但不提交,记录必要的恢复信息(如Undo日志)。
- 参与者根据执行结果回复协调者,表示是否可以提交(Yes/No)。
②提交阶段(Commit Phase)
- 如果所有参与者都回复Yes,协调者发送提交(Commit)请求给所有参与者。
- 参与者提交本地事务,并释放资源。
- 如果任何一个参与者回复No,协调者发送回滚(Rollback)请求给所有参与者。
- 参与者回滚本地事务,释放资源。
优点:
- 简单易理解,开发较容易。
- 强一致性,确保所有参与者要么全部提交,要么全部回滚。
缺点:
- 同步阻塞: 所有事务参与者在等待其他参与者响应时处于阻塞状态,性能较低。
- 单点故障: 协调者故障可能导致整个事务失败。
- 数据不一致: 在网络分区等异常情况下,可能导致部分参与者提交,部分参与者回滚,造成数据不一致。
2)三阶段提交协议(3PC)
原理:
①CanCommit阶段:
- 协调者询问参与者是否可以提交事务。
- 参与者根据自身状态回复Yes/No。
②PreCommit阶段:
- 协调者收到所有Yes回复后,发送预提交(PreCommit)请求给参与者。
- 参与者执行本地事务操作,但不提交,记录必要的恢复信息。
- 参与者回复Ack表示准备好提交。
③DoCommit阶段:
- 协调者收到所有Ack回复后,发送提交(DoCommit)请求给参与者。
- 参与者提交本地事务,并释放资源。
- 如果任何一个阶段失败,协调者发送中止(Abort)请求给所有参与者,参与者回滚本地事务。
优点:
- 引入了超时机制,一定程度上解决了协调者单点故障问题。
- 在CanCommit阶段提前检查参与者状态,减少了无效的事务操作。
缺点:
- 性能问题仍然存在,特别是在高并发场景下。
- 实现复杂,增加了系统的复杂性和故障点。
3)TCC(Try-Confirm-Cancel)事务
原理:
①Try阶段:
- 尝试执行业务操作,完成所有业务检查(一致性),预留必要的业务资源(准隔离性)。
- 参与者返回操作结果。
②Confirm阶段:
- 确认执行真正的业务操作,不作任何业务检查,只使用Try阶段预留的资源。
- Confirm操作要求具备幂等性,即多次执行结果一致。
③Cancel阶段:
- 在业务执行错误或需要回滚时,执行取消操作,释放Try阶段预留的资源。
- Cancel操作也要求具备幂等性。
优点:
- 并发度高,无长期资源锁定。
- 灵活性高,允许开发者自定义每个阶段的具体操作。
- 适用于业务流程复杂、需要长时间运行的事务场景。
缺点:
- 对应用的侵入性强,业务逻辑的每个分支都需要实现Try、Confirm、Cancel三个操作。
- 实现难度较大,需要按照网络状态、系统故障等不同的失败原因实现不同的回滚策略。
- 改造成本高,需要重构现有业务代码。
4)本地消息表
原理:
第一阶段:
- 业务操作和写本地消息表在同一个本地事务中完成。
- 如果业务操作成功,向本地消息表插入一条记录;如果失败,则回滚事务。
第二阶段:
- 定时器或单独的服务定时查询本地消息表,将待处理的消息写入消息队列。
第三阶段:
- 消费者从消息队列中读取消息,执行相应的业务操作。
- 如果操作成功,更新消息状态为已处理;如果失败,进行重试或补偿处理。
优点:
- 避免了分布式事务,实现了最终一致性。
- 适用于长事务场景,将长事务拆分为多个短事务处理。
缺点:
- 消息表会耦合到业务系统中,增加了系统的复杂性。
- 需要额外的定时器和消息队列服务,增加了系统的运维成本。
5)基于可靠消息服务的分布式事务
原理:
- 使用支持事务的消息队列(如RocketMQ的事务消息)来确保分布式事务的一致性。
- 发送方在本地事务中预发送消息到消息队列,但不立即确认。
- 如果本地事务提交成功,发送方确认消息发送;如果失败,则取消消息发送。
- 接收方从消息队列中读取消息,执行相应的业务操作,并返回处理结果。
- 如果接收方处理成功,消息队列删除消息;如果失败,消息队列重新投递消息,直到处理成功或达到最大重试次数。
优点:
- 实现了最终一致性,不需要依赖本地数据库事务。
- 适用于对一致性要求不是特别严格的场景,如异步通知、事件驱动等。
缺点:
- 实现难度大,需要消息队列支持事务消息。
- 主流消息队列(如RabbitMQ、Kafka)不支持事务消息,需要选择特定的消息队列产品。
6)Saga事务
原理:
- 将长事务拆分为多个本地短事务,由Saga事务协调器协调。
- 每个本地短事务都有对应的补偿事务,用于在失败时撤销已提交的操作。
- Saga事务按照顺序执行本地短事务,如果某个事务失败,则按照相反的顺序调用补偿事务。
优点:
- 并发度高,不用像XA事务那样长期锁定资源。
- 适用于长事务场景,如跨多个服务的业务流程。
缺点:
- 一致性较弱,对于某些业务场景(如转账)可能发生中间状态不一致的情况。
- 需要定义正常操作以及补偿操作,开发量较大。
总结
在选择分布式事务解决方案时,需要根据具体的业务场景和需求进行权衡。对于强一致性要求较高的场景,可以考虑使用XA两阶段提交或TCC事务;对于一致性要求不是特别严格、但希望提高并发性能和系统可用性的场景,可以考虑使用本地消息表、基于可靠消息服务的分布式事务或Saga事务。同时,还需要考虑系统的复杂性、运维成本以及开发人员的熟悉程度等因素。
如本文有侵权行为,请及时与本人联系,多多包涵!
小生初出茅庐,多多指教!
本文来自博客园,作者:it-小林,转载请注明原文链接:https://www.cnblogs.com/linruitao/p/18820079

浙公网安备 33010602011771号