声明: 本篇主要对所用到的技术做了归纳总结,对源码讲解较少,如果有基础的朋友可直接下载源码结合时序图更能容易理解;基础比较弱的朋友建议先看看资料自看源码这样更容易理解。这里的部分资料来源于网络,所以这里对那些资料提供者表达衷心的感谢。

此方案其核心思想是将分布式事务拆分成本地事务进行处理。通过在消费者额外新建事务消息表,消费者处理业务和记录事务消息在本地事务中完成,轮询事务消息表的数据发送事务消息,提供者基于消息中间件消费事务消息表中的事务。
1. 方案

  • 业务流程:Tss库向Saas转移库存,order为订单请求记录表,EventPublish为produce事件执行记录表,EventProces为consumer事件记录表。
  • 技术栈:Springboot+kafka+mysq+postgreSQL
  • 代码地址:https://github.com/bao17634/springboot-kafka-demo.git
  • 事件记录表字段:
  • 枚举类:
    1.1 处理流程
  • 1)在分布式事务操作的一方完成写业务数据的操作之后向本地消息表发送一个消息,本地事务能保证这个消息一定会被写入本地消息表中。
  • 2) 之后将本地消息表中的消息转发到 Kafka 等消息队列中,如果转发成功则将消息从本地消息表中删除,否则继续重新转发。
  • 3) 在分布式事务操作的另一方从消息队列中读取一个消息,并执行消息中的操作。

1.2 原理图

怎么理解kafka的分布式 kafka实现分布式事务_kafka

1.3 方案时序图

  • produce业务时序图:
    1)TssService先开启事务,然后向Order添加数据并减少Tss的库存。
    2)业务执行成功后,将需要发送给consumer的数据存到EventPublish表中,此时保存状态为NEW,保存成功后提交事务。
    3)定时器服务查找EventPublish表中状态为NEW的数据,然后将结果交给kafka,kafka发送给consumer。
    4)发送成功后,将EventPublish表中状态为NEW的数据,状态更新为PUBLISHED。
    5)更新成功后提交事务。
  • consumer业务时序图:

    1)SaasService开启事务并接收kafka发送过来的消息,将收到的消息保存到EventProcess表中,状态为NEW。
    2)保存成功后提交事务,并返回kfka消息已接收成功。
    3)定时器查询EventProcess表中状态为NEW的数据。
    4)拿到结果后处理数据,执行业务,增加Saas库存。
    5)业务执行成功后,将EventProcess表中NEW状态的数据,更新为PROCESSED状态。
    6)更新成功后提
    注!:kafka在消息消费失败时是没有重试机制的,所以在consumer先将消息存入到记录表后才定时消费消息,所以这里定时执行的程序也就是我们在consumer写的消息重试机制。

1.4 方案总结:

优点:

  • 从应用设计开发的角度实现了消息数据的可靠性,消息数据的可靠性不依赖于消息中间件,弱化了对 MQ 中间件特性的依赖。
  • produce和consumer各自使用了数据库的原生事务,最大可能的做到数据强一致性。

缺点:

  • 与具体的业务场景绑定,耦合性强,不可公用。消息数据与业务数据同库,占用业务系统资源。业务系统在使用关系型数据库的情况下,消息服务性能会受到关系型数据库并发性能的局限。
  • kafka无消息重试机制,需要开发者自定义重试机制。
  • 对数据库读写操作多,数据量大会影响性能。