分布式事务-使用队列实现最终一致性

分布式事务-扣减库存

一、最终一致性架构图

1、服务

左侧:创建订单服务Server1

右侧:扣减库存服务Server2

中间:独立消息服务Server3

2、中间件:

Kafka-MQ、MySQL-db


二、步骤

0、定义MQ,三个状态

  • prepare
  • confirm
  • ack

1、Server1

  • 生成单据号
  • 调用Server3#updateMQ接口,状态为prepare

2、Server1

  • 下单

3+5、Server1

  • 下单结束后,调用Server3#updateMQ接口,状态为confirm

4、Server3

  • 定时任务,捞取db中所有单据号(单据号id、消息id、业务类型、消息状态、消息体)

  • 遍历所有状态为prepare的单据号

    • 查询server1中#queryOrder接口

      • 如果没有用查询到订单信息,说明server1服务下单流程失败了,没有建单

        此时,直接删除db中此无用单据信息

      • 如果查询到了订单信息,说明server1服务的confirm阶段失败了

        此时,将db中此单据id对应的消息状态,更新为confirm、并sendMQ到消息队列

6、单据id对应的消息状态为confirm的MQ,被发送到MQ中了

7、server2

扣减库存服务,监听到MQ后,消费MQ

  • 扣减库存成功,则ACK

    • 调用server3#updateMQ接口,将单据id的状态改为ACK
  • 扣减库存成功,则Kafka有重试机制,也有死信机制,保障消费一定成功


三、代码实现

server3服务

1)updateMQ接口入参定义

java 复制代码
public class Message implements Serializable {
    private String orderId;
    /**
     * 业务类型:1-优选订单、2-买菜订单
     */
    private Integer businessType;

    /**
     * MQ状态:1-prepare、2-confirm、3-ack
     */
    private Integer status;
    
    private BizData bizData;
}

2)updateMQ方法内容

java 复制代码
    @Transactional
    public void updateMQ(Message mq) {
        Integer status = mq.getStatus();
        if (status == 1) {
            // saveDb
        } else if (status == 2) {
            // sendMQ2Kafka
            // updateDb(将单据状态改为2)
        } else if (status == 3) {
            // updateDb(将单据状态改为3)
        }
    }

3)定时任务

java 复制代码
    @Scheduled(cron = "0 * * * * *")
    public void craneTask() {
        // 1、拉去db
        // 2、获取状态为prepare=1的单据
        // 3.查看server1服务查询订单接口
            // 3.1 订单不存在,则删除db此条数据
            // 3.2 订单存在,  则更新db此条数据状态为confirm、然后sendMQ2Kafka
    }
server1
  • 提供查询订单接口服务
  • 在步骤1,创建订单之前时,调用server3#updateMQ接口,入参状态为prepare=1
  • 在步骤3和5,创建订单之后时,调用server3#updateMQ接口,入参状态为confirm=2
server2服务
  • 监听kafka的消息,消费,扣减库存即可
    erver3#updateMQ接口,入参状态为prepare=1
  • 在步骤3和5,创建订单之后时,调用server3#updateMQ接口,入参状态为confirm=2
server2服务
  • 监听kafka的消息,消费,扣减库存即可
    • 消费消息成功后,调用updateMQ,入参状态为ACK=3
相关推荐
笨手笨脚の17 小时前
Java 性能优化
java·jvm·数据库·性能优化·分布式锁·分布式事务·并发容器
肥猪猪爸3 天前
数据库 2PC 极简流程图
java·数据库·分布式·mysql·分布式事务·2pc
Chan163 天前
从生产到消费:Kafka 核心原理与实战指南
java·spring boot·分布式·spring·java-ee·kafka·消息队列
茶杯梦轩10 天前
从零起步学习RabbitMQ || 第二章:RabbitMQ 深入理解概念 Producer、Consumer、Exchange、Queue 与企业实战案例
服务器·后端·消息队列
初次攀爬者11 天前
Kafka 基础介绍
spring boot·kafka·消息队列
初次攀爬者12 天前
RocketMQ 消息可靠性保障与堆积处理
后端·消息队列·rocketmq
初次攀爬者12 天前
RocketMQ 集群介绍
后端·消息队列·rocketmq
初次攀爬者12 天前
RocketMQ 基础学习
后端·消息队列·rocketmq
初次攀爬者13 天前
RabbitMQ的消息模式和高级特性
后端·消息队列·rabbitmq
DemonAvenger15 天前
Kafka性能调优:从参数配置到硬件选择的全方位指南
性能优化·kafka·消息队列