# mq-springboot-reliable
**Repository Path**: zhangzhenliang/mq-springboot-reliable
## Basic Information
- **Project Name**: mq-springboot-reliable
- **Description**: 在使用MQ消息中间件时,用户经常会遇到各种问题。本框架通过 本地消息表+兜底机制 相结合的方式,有效保障数据一致性,支持RabbitMQ、RocketMQ、Kafka多种消息中间件的处理。
- **Primary Language**: Java
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 3
- **Forks**: 0
- **Created**: 2025-09-12
- **Last Updated**: 2025-11-01
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# mq-springboot-reliable
## 介绍
在使用MQ消息中间件时,用户经常会遇到各种问题。本框架通过 本地消息表+兜底机制 相结合的方式,有效保障数据一致性,支持RabbitMQ、RocketMQ、Kafka等多种消息中间件的处理。
如果本项目对您有所帮助,请帮忙点个 Star 支持一下,非常感谢!
## 问题域
#### 发送
1. 业务失败但消息发出了
2. 以为调用接口就发送出去了,但是实际未发送成功
3. 调用消息发送接口,但同步发送性能差,异步发送确认处理复杂
#### 消费
1. 消息中间件保障对同一消息“至少投递一次”,可能会出现多次业务处理
2. 投递失败,可能出现死循环消费或者超限丢弃转死信队列
## 解决方案
核心:本地消息表+消息消费成功确认+兜底机制(未成功确认补发消息或人工处理)
注意:只有消费成功才会确认,对未消费成功进行超时补发或人工处理
##### 消息发送
```mermaid
sequenceDiagram
participant A as 生产者应用
participant B as 生产者本地消息表
participant C as 消息中间件
A->>A: 事务开始
A->>A: 业务处理
A->>B: 保存消息(调用统一发送接口)
A->>A: 业务处理
A->>A: 事务提交
A->>C: 发送消息(框架自动)
```
1. 消息保存和生产者业务处理在同一个数据库事务里面,事务提交后再发送消息,保证数据一致性
2. 框架提供同一个发送接口,统一处理发送消息,会自动在在事务提交后发送消息
3. 同一个发送接口,需要传入如下参数:
- 主题:必须,Topic(rockemq)/Exchange(rabbitmq)
- 标签: 可选,Tag(rockemq)/RouteKey(rabbitmq)
- 回调确认主题:必须,Topic(rockemq)/Exchange(rabbitmq)
- 回调确认标签:可选,Tag(rockemq)/RouteKey(rabbitmq)
- 消息数据:必须,Data
- 业务ID: 可选
#### 消息消费
```mermaid
sequenceDiagram
participant A as 生产者应用
participant B as 生产者本地消息表
participant C as 消息中间件
participant D as 消费者应用
participant E as 消费者本地消息表(可与生产者相同表)
C->>D: 投递消息
D->>E: 幂等处理(根据消息ID判断)
D->>D: 业务处理
D->>E: 成功后,设置消息消费成功
E->>C: 成功后,给回到确认主题发送成功消息
C->>A: 投递消息
A->>B: 设置消息消费成功
```
1. 消息中间件保障至少投递一次
2. 根据消息ID做幂等处理
3. 如果是生产者和消费者是同一数据库,支持直接数据库中确认,不需要通过发送确认消息
##### 消费者端消费处理逻辑
```mermaid
graph TD
A[开始] --> B{幂等处理,会对消息加锁}
B -->|不能消费| H[结束]
B -->|消费成功| C[发送消费成功消息]
C -->D[解锁消息]
B -->|能消费| E[业务处理]
E -->F{是否有异常}
F -->|有| D[解锁消息]
F -->|无| J[保存消息状态为消费成功]
J -->C[发送消费成功消息]
D -->H[结束]
```
##### 幂等处理
判断消息是否可以进行消费。返回可消费,不能消费,消费成功。
```mermaid
graph TD
A[开始] --> B{尝试获取锁,如果无锁则加锁}
B -->|已有锁,返回值不能消费| H[结束]
B -->|新加锁| C{判断消息ID已存在表中}
C -->|否| E[新增消息,设置状态为消费中]
E -->|返回值可消费| H[结束]
C -->|是| F{判断消息状态}
F -->|已消费,返回值已消费| H[结束]
F -->|处理中且未超时,返回值不能消费| H[结束]
F -->|其他| G[更新消息状态为消费中]
G -->|返回值可消费| H[结束]
```
#### 兜底机制
定时轮询未消费成功的消息进行补发
```mermaid
graph TD
A[开始] --> B[查询指定时间端是否有未消费成功的消息]
B -->C[补发]
C -->D[结束]
```
1. 在发送者端直接查库,获取未消费成功的消息(用户自己编写)
2. 框架提供统一的重发接口
## 使用说明
### 数据初始化
1. 执行sql/mq_init.sql,初始化数据。
2. 如果mq.consumer.type值为2,请配置mq_producer_consume_config表中的数据,如果不配置,在收到确认消息后,由于mq_producer_consume_confirm表中没有数据,将会直接将mq_producer_message表中对应消息的确认状态直接设置为确认。
属性mq.consumer.type,消费者组类型,1表示单一消费者组,2表示多个消费者组。
#### 框架对数据表使用
对于一个消息,根据mq.consumer.type的值分了两套表
- mq.consumer.type值为1,框架会使用表mq_message。
- mq.consumer.type值为2,框架会使用表mq_producer_message、mq_producer_consume_config、mq_producer_consume_confirm、mq_consumer_idempotent。
### 属性配置说明
```aiignore
mq:
# 消息ID前缀,比如使用服务名,消息ID为 前缀+32位UUID
id-prefix: demo-
consumer:
# 消费者组类型,1表示单一消费者组,2表示多个消费者组
type: 2
# 配置同库时,是否需要通过消息进行确认;当生产者和消费者属于同一数据库(根据在本地消息表是否可以查到消息判断):设置为"true"表示通过消息确认机制进行确认,设置为"false"表示直接通过数据库确认
same-database-confirmation: false
# 幂等
idempotent:
# redis幂等锁前缀,幂等锁名称为 前缀:消费者组:消息ID
lock-prefix: "mq:idempotent:"
# 幂等锁过期时间(秒)
expire-time: 5
```
### rabbitmq
#### 配置
pom.xml,增加对框架依赖
```aiignore
xyz.zhenliang.reliable
mq-springboot-reliable-mybatisplus
1.0.0
xyz.zhenliang.reliable
mq-springboot-reliable-rabbitmq
1.0.0
```
pom.xml中其他配置如Rabbitmq、JSON、mybatis plus、Redis配置
```aiignore
org.springframework.boot
spring-boot-starter-amqp
com.fasterxml.jackson.datatype
jackson-datatype-jsr310
com.baomidou
mybatis-plus-boot-starter
org.springframework.boot
spring-boot-starter-data-redis
```
application.yml配置文件需要包含JSON、RabbitMQ、MySQL、Redis等相关组件的配置,本文档示例中仅展示RabbitMQ和Jackson(JSON处理)的配置部分。
```aiignore
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: Asia/Shanghai
serialization:
write-dates-as-timestamps: false # 禁用时间戳
deserialization:
fail-on-unknown-properties: false
rabbitmq:
host: localhost
port: 5672
username: admin
password: Demo123
# 虚拟主机,默认是"/"
virtual-host: /
# 开启消息确认机制
publisher-confirm-type: correlated
publisher-returns: true
listener:
simple:
# 单个消费者预取消息个数,springboot默认250
prefetch: 10
# 消费者并发设置
concurrency: 1
max-concurrency: 10
# 消费重试配置
retry:
enabled: true
max-attempts: 3
initial-interval: 1000ms
multiplier: 2.0
max-interval: 10000ms
template:
# 发送重试配置
retry:
enabled: true # 总开关:是否启用重试机制
initial-interval: 1000ms # 首次重试的间隔时间(第一次失败后等1秒再试)
multiplier: 2 # 间隔乘数(下一次的间隔 = 上一次间隔 * multiplier)
max-attempts: 3 # 最大重试次数(包括第一次发送,总共尝试3次)
max-interval: 10000ms # 最大重试间隔(无论乘数计算出的值多大,都不会超过10秒)
# 无法路由到队列,返回处理,会执行ReturnCallback
mandatory: true
```
#### 发送
代码注入接口xyz.zhenliang.reliable.mq.core.IMqSender
```aiignore
@Autowired
private IMqSender mqSender;
```
发送接口说明:
```aiignore
/**
* 发送消息到MQ
*
* @param topic 消息主题,用于分类消息类型
* @param tag 消息标签,用于进一步细化消息分类
* @param data 消息数据内容,具体业务数据
* @param businessId 业务唯一标识,用于业务追踪
* @param confirmTopic 确认消息主题,用于发送确认消息
* @param confirmTag 确认消息标签,用于发送确认消息的标签
* @param 消息数据类型,支持泛型
* @return MqMsg 消息对象,包含消息的完整信息
*/
public MqMsg sendMsg(String topic, String tag, T data, String businessId, String confirmTopic, String confirmTag);
```
使用示例reliable-demo/rabbitmq-demo/xyz.zhenliang.reliable.demo.service.impl.DemoService
```aiignore
public MqMsg send(OrderDTO orderDTO) {
return mqSender.sendMsg(DemoConfig.ORDER_EXCHANGE_NAME, DemoConfig.ORDER_ROUTING_KEY,
orderDTO, orderDTO.getOrderId(), DemoConfig.CONFIRM_EXCHANGE_NAME, DemoConfig.CONFIRM_ROUTING_KEY);
}
```
#### 消费
代码注入接口xyz.zhenliang.reliable.mq.core.IMqConsumer
```aiignore
@Autowired
private IMqConsumer mqConsumer;
```
接口说明,包含消息消费、消息确认
```aiignore
/**
* 消费消息
*
* @param consumerGroup 消费者组
* @param mqMsg 消息对象
* @param handler 消息处理器
* @param 消息内容类型
*/
default void consume(String consumerGroup, MqMsg mqMsg, IMsgHandler handler) {
}
/**
* 消费消息
*
* @param consumerGroup 消费者组
* @param mqMsgStr 消息字符串
* @param typeReference 消息类型引用
* @param handler 消息处理器
* @param 消息内容类型
*/
default void consume(String consumerGroup, String mqMsgStr, TypeReference> typeReference, IMsgHandler handler) {
}
/**
* 消费成功确认
*
* @param mqConsumeConfirmMsg 消费确认消息
*/
default void consumeSuccessConfirm(MqConsumeConfirmMsg mqConsumeConfirmMsg) {
}
/**
* 消费成功确认
*
* @param mqConsumeConfirmMsgStr 消费确认消息字符串
*/
default void consumeSuccessConfirm(String mqConsumeConfirmMsgStr) {
}
```
消费示例reliable-demo/rabbitmq-demo/xyz.zhenliang.reliable.demo.consumer.listener.OrderListener
```aiignore
@RabbitListener(queues = DemoConfig.ORDER_QUEUE_NAME)
public void handleOrder(MqMsg message) {
mqConsumer.consume(DemoConfig.ORDER_QUEUE_NAME, message, this::handleData);
}
public void handleData(MqMsg msgDTO) {
OrderDTO orderDTO = msgDTO.getData();
orderHandler.handleOrder(orderDTO);
}
```
消费确认示例reliable-demo/rabbitmq-demo/xyz.zhenliang.reliable.demo.consumer.listener.OrderListener
```aiignore
@RabbitListener(queues = DemoConfig.CONFIRM_QUEUE_NAME)
public void handleConfirm(MqConsumeConfirmMsg message) {
mqConsumer.consumeSuccessConfirm(message);
}
```
### rocketmq
#### 配置
pom.xml,增加对框架依赖
```aiignore
xyz.zhenliang.reliable
mq-springboot-reliable-mybatisplus
1.0.0
xyz.zhenliang.reliable
mq-springboot-reliable-rocketmq
1.0.0
```
pom.xml中其他配置如rocketmq、JSON、mybatis plus、Redis配置
```aiignore
xyz.zhenliang.reliable
mq-springboot-reliable-rocketmq
com.fasterxml.jackson.datatype
jackson-datatype-jsr310
com.baomidou
mybatis-plus-boot-starter
org.springframework.boot
spring-boot-starter-data-redis
```
application.yml配置文件需要包含JSON、rocketmq、MySQL、Redis等相关组件的配置,本文档示例中仅展示rocketmq和Jackson(JSON处理)的配置部分。
```aiignore
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: Asia/Shanghai
serialization:
write-dates-as-timestamps: false # 禁用时间戳
deserialization:
fail-on-unknown-properties: false
rocketmq:
name-server: localhost:9876
producer:
group: demo-producer
# 发送消息超时时间(毫秒)
send-message-timeout: 3000
# 异步发送失败重试次数,默认为2
retry-times-when-send-async-failed: 2
# 消息最大大小(字节),默认4MB
max-message-size: 4194304
```
#### 发送
代码注入接口xyz.zhenliang.reliable.mq.core.IMqSender
```aiignore
@Autowired
private IMqSender mqSender;
```
发送接口说明:
```aiignore
/**
* 发送消息到MQ
*
* @param topic 消息主题,用于分类消息类型
* @param tag 消息标签,用于进一步细化消息分类
* @param data 消息数据内容,具体业务数据
* @param businessId 业务唯一标识,用于业务追踪
* @param confirmTopic 确认消息主题,用于发送确认消息
* @param confirmTag 确认消息标签,用于发送确认消息的标签
* @param 消息数据类型,支持泛型
* @return MqMsg 消息对象,包含消息的完整信息
*/
public MqMsg sendMsg(String topic, String tag, T data, String businessId, String confirmTopic, String confirmTag);
```
使用示例reliable-demo/rocketmq-demo/xyz.zhenliang.reliable.demo.service.impl.DemoService
```aiignore
public MqMsg send(OrderDTO orderDTO) {
return mqSender.sendMsg(DemoConstant.ORDER_TOPIC, DemoConstant.ORDER_TAG,
orderDTO, orderDTO.getOrderId(), DemoConstant.CONFIRM_TOPIC, DemoConstant.ORDER_TAG);
}
```
#### 消费
代码注入接口xyz.zhenliang.reliable.mq.core.IMqConsumer
```aiignore
@Autowired
private IMqConsumer mqConsumer;
```
接口说明,包含消息消费、消息确认
```aiignore
/**
* 消费消息
*
* @param consumerGroup 消费者组
* @param mqMsg 消息对象
* @param handler 消息处理器
* @param 消息内容类型
*/
default void consume(String consumerGroup, MqMsg mqMsg, IMsgHandler handler) {
}
/**
* 消费消息
*
* @param consumerGroup 消费者组
* @param mqMsgStr 消息字符串
* @param typeReference 消息类型引用
* @param handler 消息处理器
* @param 消息内容类型
*/
default void consume(String consumerGroup, String mqMsgStr, TypeReference> typeReference, IMsgHandler handler) {
}
/**
* 消费成功确认
*
* @param mqConsumeConfirmMsg 消费确认消息
*/
default void consumeSuccessConfirm(MqConsumeConfirmMsg mqConsumeConfirmMsg) {
}
/**
* 消费成功确认
*
* @param mqConsumeConfirmMsgStr 消费确认消息字符串
*/
default void consumeSuccessConfirm(String mqConsumeConfirmMsgStr) {
}
```
消费示例reliable-demo/rocketmq-demo/xyz.zhenliang.reliable.demo.consumer.listener.OrderListener
```aiignore
@RocketMQMessageListener(
topic = DemoConstant.ORDER_TOPIC,
consumerGroup = DemoConstant.ORDER_CONSUMER_GROUP
)
@Component
public class OrderListener implements RocketMQListener> {
private static final Logger log = LoggerFactory.getLogger(OrderListener.class);
@Autowired
private OrderHandler orderHandler;
@Autowired
private IMqConsumer mqConsumer;
/**
* 处理接收到的订单消息
*
* @param message 订单消息对象,包含订单数据和消息相关信息
*/
@Override
public void onMessage(MqMsg message) {
// 调用通用的消息消费方法,处理订单消息
mqConsumer.consume(DemoConstant.ORDER_CONSUMER_GROUP, message, this::handleData);
}
/**
* 实际处理订单数据的业务逻辑
*
* @param msgDTO 包含订单数据的消息对象
*/
public void handleData(MqMsg msgDTO) {
OrderDTO orderDTO = msgDTO.getData();
//if(true) throw new RuntimeException("xxxx");
// 调用订单处理器处理具体的订单业务逻辑
orderHandler.handleOrder(orderDTO);
}
}
```
消费确认示例reliable-demo/rocketmq-demo/xyz.zhenliang.reliable.demo.consumer.listener.ConfirmListener
```aiignore
@RocketMQMessageListener(
topic = DemoConstant.CONFIRM_TOPIC,
consumerGroup = DemoConstant.CONFIRM_CONSUMER_GROUP
)
@Component
public class ConfirmListener implements RocketMQListener {
private static final Logger log = LoggerFactory.getLogger(ConfirmListener.class);
@Autowired
private IMqConsumer mqConsumer;
/**
* 监听并处理消费确认消息
*
* @param message 消费确认消息对象
*/
@Override
public void onMessage(MqConsumeConfirmMsg message) {
// 调用MQ消费者组件处理消费成功的确认逻辑
mqConsumer.consumeSuccessConfirm(message);
}
}
```
### kafka
#### 配置
pom.xml,增加对框架依赖
```aiignore
xyz.zhenliang.reliable
mq-springboot-reliable-mybatisplus
1.0.0
xyz.zhenliang.reliable
mq-springboot-reliable-kafka
1.0.0
```
pom.xml中其他配置如kafka、JSON、mybatis plus、Redis配置
```aiignore
org.springframework.kafka
spring-kafka
com.fasterxml.jackson.datatype
jackson-datatype-jsr310
com.baomidou
mybatis-plus-boot-starter
org.springframework.boot
spring-boot-starter-data-redis
```
application.yml配置文件需要包含JSON、kafka、MySQL、Redis等相关组件的配置,本文档示例中仅展示RabbitMQ和Jackson(JSON处理)的配置部分。
```aiignore
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: Asia/Shanghai
serialization:
write-dates-as-timestamps: false # 禁用时间戳
deserialization:
fail-on-unknown-properties: false
kafka:
# Kafka地址
bootstrap-servers: localhost:9094
# 生产者配置
producer:
# 消息确认机制
acks: all # 或 -1,确保消息被完全确认
# 重试配置
retries: 2
# 批处理大小,单位为字节(32KB),Kafka 会将多个消息打包成批次发送以提高吞吐量
batch-size: 32768
# 生产者缓冲区大小,单位为字节(32MB),当生产者发送速度超过 Kafka 处理速度时,消息会暂存在这个缓冲区中
buffer-memory: 33554432
# 消息序列化
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.apache.kafka.common.serialization.StringSerializer
properties:
# 生产者等待 Kafka broker 响应的最长时间
request.timeout.ms: 40000
# 消息投递超时时间,3分钟
delivery.timeout.ms: 180000
# 消息压缩算法,使用 zstd 算法压缩消息
compression.type: zstd
# 确保可以发送 4MB 消息
max.request.size: 5242880 # 5MB
consumer:
properties:
# 会话超时
session.timeout.ms: 30000
# 轮询超时
max.poll.interval.ms: 300000
# 获取大小
max.partition.fetch.bytes: 4194304 # 4MB
```
#### 发送
代码注入接口xyz.zhenliang.reliable.mq.core.IMqSender
```aiignore
@Autowired
private IMqSender mqSender;
```
发送接口说明:
```aiignore
/**
* 发送消息到MQ
*
* @param topic 消息主题,用于分类消息类型
* @param tag 消息标签,用于进一步细化消息分类
* @param data 消息数据内容,具体业务数据
* @param businessId 业务唯一标识,用于业务追踪
* @param confirmTopic 确认消息主题,用于发送确认消息
* @param confirmTag 确认消息标签,用于发送确认消息的标签
* @param 消息数据类型,支持泛型
* @return MqMsg 消息对象,包含消息的完整信息
*/
public MqMsg sendMsg(String topic, String tag, T data, String businessId, String confirmTopic, String confirmTag);
```
使用示例reliable-demo/kafka-demo/xyz.zhenliang.reliable.demo.service.impl.DemoService
```aiignore
public MqMsg send(OrderDTO orderDTO) {
return mqSender.sendMsg(DemoConstant.ORDER_TOPIC, DemoConstant.ORDER_TAG,
orderDTO, orderDTO.getOrderId(), DemoConstant.CONFIRM_TOPIC, DemoConstant.ORDER_TAG);
}
```
#### 消费
代码注入接口xyz.zhenliang.reliable.mq.core.IMqConsumer
```aiignore
@Autowired
private IMqConsumer mqConsumer;
```
接口说明,包含消息消费、消息确认
```aiignore
/**
* 消费消息
*
* @param consumerGroup 消费者组
* @param mqMsg 消息对象
* @param handler 消息处理器
* @param 消息内容类型
*/
default void consume(String consumerGroup, MqMsg mqMsg, IMsgHandler handler) {
}
/**
* 消费消息
*
* @param consumerGroup 消费者组
* @param mqMsgStr 消息字符串
* @param typeReference 消息类型引用
* @param handler 消息处理器
* @param 消息内容类型
*/
default void consume(String consumerGroup, String mqMsgStr, TypeReference> typeReference, IMsgHandler handler) {
}
/**
* 消费成功确认
*
* @param mqConsumeConfirmMsg 消费确认消息
*/
default void consumeSuccessConfirm(MqConsumeConfirmMsg mqConsumeConfirmMsg) {
}
/**
* 消费成功确认
*
* @param mqConsumeConfirmMsgStr 消费确认消息字符串
*/
default void consumeSuccessConfirm(String mqConsumeConfirmMsgStr) {
}
```
消费示例reliable-demo/kafka-demo/xyz.zhenliang.reliable.demo.consumer.listener.OrderListener
```aiignore
@KafkaListener(
topics = DemoConstant.ORDER_TOPIC,
groupId = DemoConstant.ORDER_CONSUMER_GROUP
)
public void handleOrder(@Payload String message) {
mqConsumer.consume(DemoConstant.ORDER_CONSUMER_GROUP, message
, new TypeReference>() {
}, this::handleData);
}
public void handleData(MqMsg msgDTO) {
OrderDTO orderDTO = msgDTO.getData();
//if(true) throw new RuntimeException("xxxx");
orderHandler.handleOrder(orderDTO);
}
```
消费确认示例reliable-demo/kafka-demo/xyz.zhenliang.reliable.demo.consumer.listener.OrderListener
```aiignore
@KafkaListener(
topics = DemoConstant.CONFIRM_TOPIC,
groupId = DemoConstant.CONFIRM_CONSUMER_GROUP
)
public void handleConfirm(@Payload String message) {
mqConsumer.consumeSuccessConfirm(message);
}
```
### 兜底
#### 未确认消息查询
属性mq.consumer.type,消费者组类型,1表示单一消费者组,2表示多个消费者组。
```aiignore
值为1,一个消息只有单一消费者组
select * from mq_message where confirm_status=0
```
```aiignore
值为2,一个消费者有一个或多个消费者组
SELECT * FROM mq_producer_message where confirm_status=0
```
#### 重发
代码注入接口xyz.zhenliang.reliable.mq.core.IMqSender
```aiignore
@Autowired
private IMqSender mqSender;
```
发送接口说明:
```aiignore
/**
* 根据消息ID重新发送消息
*
* @param msgId 消息唯一标识,用于定位需要重发的消息
*/
public void resendMsg(String msgId);
```
## 框架设计
#### 代码结构
reliable-main (父模块)
- reliable-commons (公共模块,封装工具类等)
- reliable-core (核心模块,封装整体框架结构,依赖reliable-commons)
- reliable-mq (消息队列模块,封装消息队列相关代码,依赖reliable-core,实现接口IMqProducer)
- reliable-mq-rabbitmq (rabbitmq实现)
- reliable-mq-rocketmq (rocketmq实现)
- reliable-mq-kafka (kafka实现)
- reliable-persistence (持久化)
- reliable-persistence-mybatisplue (通过mybatis进行持久化,实现接口IMqIdempotent和IMqPersister)
#### 表结构说明
对于一个消息,根据mq.consumer.type的值分了两套表。支持生产者和消费者连接不同的数据库。
- mq.consumer.type值为1,一个消息只会被一个消费者消费
| 表 | 名称 | 说明 |
|-----------|---------|-----------------------------------|
| mq_message | mq消息表 | 发送时候写入本地数据,消费(幂等和成功标志)和消费确认都在该表进行 |
- mq.consumer.type值为2,一个消息只会被一个消费者消费,消息消费确认需要针对多消费者情况
| 表 | 名称 | 说明 |
|---------|---------|------------------------------------------------------------|
| mq_producer_consume_config | MQ生产者消费配置表 | 手工配置 |
| mq_producer_message | mq消息表 | 发送时候写入数据,全部消费完成(根据mq_producer_consume_confirm未确认数量)会修改该表确认状态 |
| mq_producer_consume_confirm | MQ生产者消费确认表 | 发送时候根据配置表写入数据,消费确认将会修改表中确认状态 |
| mq_consumer_idempotent | MQ消费者幂等表 | 消费时候写入,用于幂等判断,消费成功和失败都会修改该表状态 |
####
## 示例说明
#### 代码结构
reliable-demo (示例的父模块,下面都是它的子模块)
- demo-core (示例核心模块)
- rabbitmq-demo (依赖核心模块,封装rabbitmq相关代码)
- rocketmq-demo (依赖核心模块,封装rocketmq相关代码)
- kafka-demo(依赖核心模块,封装kafka相关代码)
#### rabbitmq示例
中间件部署
```aiignore
cd deploy
docker compose -f docker-compose-rabbitmq.yml up -d
```
启动应用
```aiignore
xyz.zhenliang.reliable.demo.DemoRabbitmqApplication
```
访问应用接口界面,访问地址如下,点击菜单mq示例,尝试发送消息和重发消息接口调用
```aiignore
http://localhost:10000/doc.html
截图见docs/images中的图片
```
rabbitmq管理控制台
```aiignore
http://localhost:15672
admin/Demo123
```
#### rocketmq示例
中间件部署
修改deploy/rocketmq/broker/conf/broker.conf中brokerIP1为自己机器的IP
```aiignore
brokerIP1=192.168.0.107
```
启动中间件
```aiignore
cd deploy
docker compose -f docker-compose-rocketmq.yml up -d
```
启动应用
```aiignore
xyz.zhenliang.reliable.demo.DemoRocketmqApplication
```
访问应用接口界面,访问地址如下,点击菜单mq示例,尝试发送消息和重发消息接口调用
```aiignore
http://localhost:10000/doc.html
截图见docs/images中的图片
```
rocketmq管理控制台
```aiignore
http://localhost:18080/
```
#### kafka示例
中间件部署
```aiignore
cd deploy
docker compose -f docker-compose-kafka.yml up -d
```
启动应用
```aiignore
xyz.zhenliang.reliable.demo.DemoKafkaApplication
```
访问应用接口界面,访问地址如下,点击菜单mq示例,尝试发送消息和重发消息接口调用
```aiignore
http://localhost:10000/doc.html
截图见docs/images中的图片
```
kafka管理控制台
```aiignore
http://localhost:18082/
```