RabbitMQ的事务机制
RabbitMQ的事务机制用于确保消息在生产、传输和消费过程中的可靠性。通过事务机制,可以确保消息在出现异常时不会丢失或重复消费。
事务机制的操作
在RabbitMQ中,事务机制的操作包括以下三个步骤:
-
开启事务 :
channel.txSelect()
开启事务模式,告知RabbitMQ接下来的操作需要事务控制。
-
提交事务 :
channel.txCommit()
提交事务,确认所有消息成功发布或处理。
-
回滚事务 :
channel.txRollback()
发生异常时回滚事务,撤销所有未提交的操作。
事务机制的优缺点
优点:
- 可靠性高,确保消息不会丢失。
缺点:
- 性能较低,每条消息都要等待事务提交或回滚,严重影响吞吐量。
- 较少用于高并发场景,更多使用Confirm机制来替代事务机制。
Spring Boot中使用RabbitMQ事务
1. 引入依赖
在pom.xml
中添加RabbitMQ依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
-
配置文件(application.yml)
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
3. 生产者代码
在生产者中使用事务控制:
java
package com.example.rabbitmq.producer;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate.TransactionCallback;
import org.springframework.amqp.rabbit.transaction.RabbitTransactionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.Transactional;
@Configuration
public class RabbitMQConfig {
@Bean
public RabbitTransactionManager rabbitTransactionManager(ConnectionFactory connectionFactory) {
return new RabbitTransactionManager(connectionFactory);
}
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
template.setChannelTransacted(true); // 开启事务
return template;
}
}
- 生产消息
java
package com.example.rabbitmq.producer;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Transactional // 事务注解
public void sendMessage(String exchange, String routingKey, String message) {
try {
rabbitTemplate.convertAndSend(exchange, routingKey, message);
System.out.println("消息发送成功:" + message);
} catch (Exception e) {
System.err.println("消息发送失败:" + e.getMessage());
throw e; // 触发事务回滚
}
}
}
- 消费者代码
java
package com.example.rabbitmq.consumer;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class MessageConsumer {
@Transactional // 事务注解
@RabbitListener(queues = "test-queue")
public void receiveMessage(String message) {
System.out.println("接收到消息:" + message);
if ("error".equals(message)) {
throw new RuntimeException("消费失败,触发事务回滚");
}
}
}
RabbitMQ的限流和负载均衡
在RabbitMQ中,限流 和负载均衡是确保系统在高并发和大流量场景下稳定运行的关键机制。以下是这两个机制的详细介绍:
一、限流(流量控制)
RabbitMQ中的限流机制通过**Qos(Quality of Service)**来实现。
核心方法是:
- basicQos(int prefetchCount):用于限制消费者每次拉取的消息数量。
- prefetchCount :
- 1:消费者一次只接收一条消息,处理完后才继续接收下一条。
- n:消费者可以同时处理n条消息。
- 0:没有限制(默认)。
作用:
- 防止消费者压力过大导致消息堆积。
- 保证消费者逐条确认,避免消息丢失。
二、负载均衡
RabbitMQ的负载均衡是通过轮询分发 和公平分发来实现的:
-
轮询分发(Round-Robin)
- 默认模式。
- 消息均匀地分配给每个消费者。
- 缺点:无法考虑消费者的消费能力差异,导致性能不均衡。
-
公平分发(Fair Dispatch)
- 结合Qos机制实现。
- 通过设置
prefetchCount=1
,使消费者处理完消息后才继续获取下一条,保证消息不会被堆积在性能较差的消费者上。
三、Spring Boot中实现限流和负载均衡
配置文件方式(application.yml)
我们可以直接在配置文件中进行消费者并发数、预取数量(限流)等配置:
示例配置文件(application.yml)
java
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
listener:
simple:
concurrency: 5 # 最小并发消费者数量
max-concurrency: 10 # 最大并发消费者数量
prefetch: 1 # 每个消费者每次只接收1条消息(限流)
acknowledge-mode: manual # 手动确认消息
二、生产者代码
java
package com.example.rabbitmq.producer;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendMessage(String message) {
rabbitTemplate.convertAndSend("test-queue", message);
System.out.println("消息发送:" + message);
}
public void sendBatchMessages() {
for (int i = 1; i <= 20; i++) {
sendMessage("Message " + i);
}
}
}
三、消费者代码
java
package com.example.rabbitmq.consumer;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
@Service
public class MessageConsumer {
@RabbitListener(queues = "test-queue")
public void receiveMessage(String message, Channel channel) throws Exception {
try {
System.out.println(Thread.currentThread().getName() + " 接收到消息:" + message);
Thread.sleep(1000); // 模拟耗时操作
channel.basicAck(channel.getNextPublishSeqNo(), false); // 手动确认
} catch (Exception e) {
channel.basicNack(channel.getNextPublishSeqNo(), false, true); // 失败重新入队
System.err.println("消费失败:" + message);
}
}
}
四、配置解读
在配置文件中,我们通过以下几个参数来控制限流和负载均衡:
- concurrency:最小并发消费者数量。
- max-concurrency:最大并发消费者数量,动态调整消费者数量。
- prefetch:每次拉取的消息数量(限流)。
- acknowledge-mode:手动确认消息消费成功,防止消息丢失。