文章目录:
- 前言
- 什么是最终一致性?
- 实现方案
- 代码实现
- 小结
- 推荐阅读
前言
这篇文章是《关于分布式事务的理解》的后续篇:分布式事务之最终一致性实现方案。
还是那个电商需求,一个订单支付完成后的业务场景,有如下操作:
- 更改订单的状态为 “已支付”
- 扣减商品库存
- 给会员增加积分
- 创建出库单通知仓库发货
咱们使用 最终一致性方案 去实现它。
什么是最终一致性?
从字面上看就是 保证数据最后的一致性 就可以了。
为了减少系统代价,如果中间节点处理失败,其他节点一般不会自动回滚,而是通过重试机制和人工参与的方式对失败数据进行处理,从而来保证数据最后的一致性。
实现方案
使用 本地消息表 + 后台任务 + 消息队列 + 接口幂等性。
本地消息表:在对应业务数据库中增加的本地消息表,这张表存储业务产生的消息,通过 本地事务 保证业务数据和消息数据的一致性,比如:msg_published
和 msg_received
表示发布消息表和接收消息表,在消息表中会有一个状态来标识业务是否执行成功。
后台任务:当消息表中有执行失败的业务信息时,后台任务就会按照配置的重试策略进行重试,例如重试策略为当发送和消费消息的过程中失败会立即重试 3 次,在 3 次以后将进入重试轮询;重试将在发送和消费消息失败的 4分钟后 开始,这是为了避免设置消息状态延迟导致可能出现的问题;后续就会每隔 1 分钟之后重试一次,默认的最高重试次数为 50 次,当达到 50 次时,就不会重试了,通过发邮件/微信/钉钉/短信的方式通知人工去处理,通知时需要考虑消息降噪。
消息队列:跨服务之间的调用使用消息队列,来实现服务解耦。
接口幂等性:接口需要保证同一操作发起的一次请求或者多次请求的结果必须是一致的。
代码实现
推荐一个 C#
开源项目 CAP[1],大家可以参考一下。
这个项目只支持 C#
代码去集成,如果是其他语言可以参考其设计思路,然后进行一个简单的实现。
小结
本文纯属抛砖引玉,有问题,欢迎批评指正。
你有更好的实现方案吗?欢迎留言~
推荐阅读
- 回答两个被频繁问到的代码写法问题
- 根据使用者反馈,对开源项目 go-gin-api 新增两个功能
- 关于处理电商系统订单状态的流转,分享下我的技术方案(附带源码)
- 我是怎么写 Git Commit message 的?
参考资料
[1]