镜像队列配置
镜像队列通过将队列内容复制到集群中的多个节点,确保单个节点故障时消息不丢失,消费者可继续从新的Master节点消费。
定义
镜像队列基于Policy机制配置,通过ha-mode参数指定镜像模式(all/exactly/nodes),使队列在多个节点间同步复制消息和消费者状态。
Maven依赖
XML
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.20.0</version>
</dependency>
配置方式
通过rabbitmqctl配置
Bash
# 模式一:镜像到所有节点
rabbitmqctl set_policy ha-all "^ha\." '{"ha-mode":"all"}' --apply-to queues
# 模式二:镜像到指定数量节点
rabbitmqctl set_policy ha-two "^orders\." '{"ha-mode":"exactly","ha-params":2}' --apply-to queues
# 模式三:镜像到特定节点
rabbitmqctl set_policy ha-nodes "^logs\." '{"ha-mode":"nodes","ha-params":["rabbit@node-b","rabbit@node-c"]}' --apply-to queues
# 设置同步模式(默认为automatic)
rabbitmqctl set_policy ha-sync "^sync-queue\." '{"ha-mode":"all","ha-sync-mode":"manual"}' --apply-to queues
Policy参数说明
| 参数 | 说明 |
|---|---|
| ha-mode | 镜像模式:all(全部节点)、exactly(指定数量)、nodes(指定节点) |
| ha-params | 配合exactly时为节点数量;配合nodes时为节点名称数组 |
| ha-sync-mode | 同步模式:automatic(自动)、manual(手动)。自动模式下新Slave立即同步,可能影响写入性能 |
| ha-promote-on-shutdown | Master关闭时是否提升Slave:when-correctly-synced(仅已同步时提升)、always(总是提升) |
Java代码声明队列
Java
import com.rabbitmq.client.*;
import java.util.HashMap;
import java.util.Map;
public class MirroredQueueExample {
private static final String QUEUE_NAME = "ha.orders";
private static final String EXCHANGE_NAME = "orders_exchange";
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
factory.setUsername("guest");
factory.setPassword("guest");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
// 声明交换机
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT, true);
// 声明持久化队列(镜像由Policy控制,此处无需特殊参数)
Map<String, Object> queueArgs = new HashMap<>();
channel.queueDeclare(QUEUE_NAME, true, false, false, queueArgs);
// 绑定队列到交换机
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "orders");
// 发布持久化消息
String message = "order-998877";
channel.basicPublish(EXCHANGE_NAME, "orders",
MessageProperties.PERSISTENT_TEXT_PLAIN,
message.getBytes("UTF-8"));
System.out.println("发送: " + message);
// 消费消息
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String msg = new String(delivery.getBody(), "UTF-8");
System.out.println("收到: " + msg);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
};
channel.basicConsume(QUEUE_NAME, false, deliverCallback, consumerTag -> {});
}
}
镜像队列运行逻辑
text
Master节点: 处理所有读写请求
│
├──▶ 写入消息
│ │
│ ├──▶ 本地存储
│ │
│ └──▶ 同步到所有Slave
│ │
│ ├──▶ Node-B Slave
│ │
│ └──▶ Node-C Slave
│
└──▶ 消费者消费(仅Master处理)
- 所有读写操作由Master处理,Slave仅接收同步数据
- 消费者连接到Master,消费后Master将ACK同步到Slave
- Master宕机时,最老的Slave提升为新的Master
ha-sync-mode=manual时,新加入的Slave不会自动同步已有消息,需管理员手动触发同步。适合大规模集群,避免同步流量冲击网络。
注意事项
性能损耗:每次写入需复制到所有镜像节点,写入延迟随节点数线性增长。
脑裂风险:网络分区时,若多个节点均认为自己是Master,可能导致数据不一致。使用
pause_minority策略可缓解。同步模式选择:
automatic保证新Slave立即同步,适合小规模集群;manual适合大规模集群,需手动触发初始同步。与Quorum Queue互斥:同一队列不能同时使用镜像和仲裁模式,需选择其中一种。
Policy优先级:多个Policy匹配时,优先级按Priority参数决定,数值大的优先。
要点总结
- 镜像队列通过Policy的
ha-mode参数配置,支持all、exactly、nodes三种模式 - 所有读写操作由Master处理,Slave仅接收同步数据
- Master宕机时最老Slave自动接管,保障队列持续可用
ha-sync-mode控制新Slave同步方式,automatic立即同步,manual需手动触发- 镜像复制增加写入延迟,节点越多性能损耗越大
📝 发现内容有误?点击此处直接编辑