RabbitMQ—运维篇
RabbitMQ安装
- RabbitMQ需要依赖erlang,如果普通安装需要安装erlang并保证二者兼容,因此选择较为简单的docker安装方式
1.获取rabbitmq镜像
docker pull rabbitmq:3.11.19-management #rabbitmq-management表示带有客户端(控制台)
docker pull rabbitmq:3.11.19 #如果只要服务端
2.启动rabbitmq容器
docker run \
-d \
--name rabbitmq \
--hostname=rabbitmqNode1 \ #设置hostname,后续做集群时方便管理,这里将rabbitmq设为节点1
-v rabbitmq-plugins:/plugins \ #将rabbitmq的plugin目录进行挂载,以便后续进行安装rabbitmq插件
-v rabbitmq:/var/lib/rabbitmq \
-e RABBITMQ_DEFAULT_USER=admin \ #设置rabbitmq管理账户为admin、密码为admin
-e RABBITMQ_DEFAULT_PASS=admin \
-e RABBITMQ_ERLANG_COOKIE='rabbitcookie' \ #集群部署时,Erlang Cookie 值必须都相同
-p 15672:15672 \ #15672是客户端的端口,5672是服务端的端口
-p 5672:5672 \
--restart=always \
rabbitmq:3.11.19-management
3.开启防火墙
firewall-cmd --zone=public --add-port=5672/tcp --permanent
firewall-cmd --zone=public --add-port=15672/tcp --permanent
firewall-cmd --reload
firewall-cmd --list-all # 查看已经开放的端口号
3.测试rabbitmq是否安装完成
- 访问
部署IP:15672
,观察rabbitmq是否正常部署
RabbitMQ集群
- RabbitMQ集群部署时,必须保证Erlang Cookie相同
普通集群模式
-
目的:提高MQ的吞吐量
-
原理:普通集群模式下,broker之间复制元数据
- 生产者给一个broker发送消息,消费者连接的是另一个broker
- 生产者连接的broker会将消息转发给消费者的broker,这样就实现了分离消费端和生产端
-
普通集群模式进一步提高了MQ效率,但不保证高可用,如果一个节点宕机仍然会丢失消息
#如果要再加第三个节点就再--link
docker run -d --name rabbitmqCluster02 --hostname=node2 -v rabbitmqCluster02.plugins:/plugins -v rabbitmqCluster02:/var/lib/rabbitmq -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' -p 15673:15672 -p 5673:5672 --link rabbitmqCluster01:node1 rabbitmq:3.11.19-management
#节点2,进入容器,开启集群
rabbitmqctl stop_apprabbitmqctl resetrabbitmqctl join_cluster rabbit@node1rabbitmqctl start_app#节点1,进入容器,重载配置
rabbitmqctl stop_apprabbitmqctl resetrabbitmqctl start_app
#这里加了一个--add-host,即将集群中其他的节点加入,这样才能相互通信
#这里演示一主一从,创建node1节点时就将node2节点也加入,如果如果需要多个就增加几个add-host参数即可
docker run \
-d \
--name rabbitmq \
-v rabbitmq-plugins:/plugins \
-v rabbitmq:/var/lib/rabbitmq \
--hostname=node1 \
--add-host=node2:192.168.1.43 \
-e RABBITMQ_DEFAULT_USER=admin \
-e RABBITMQ_DEFAULT_PASS=admin \
-e RABBITMQ_ERLANG_COOKIE='rabbitcookie' \
-p 4369:4369 \
-p 25672:25672 \
-p 15672:15672 \
-p 5672:5672 \
--restart=always \
rabbitmq:3.11.19-managementdocker run \
-d \
--name rabbitmq \
-v rabbitmq-plugins:/plugins \
-v rabbitmq:/var/lib/rabbitmq \
--hostname=node2 \
--add-host=node1:192.168.1.35 \
-e RABBITMQ_DEFAULT_USER=admin \
-e RABBITMQ_DEFAULT_PASS=admin \
-e RABBITMQ_ERLANG_COOKIE='rabbitcookie' \
-p 4369:4369 \
-p 25672:25672 \
-p 15672:15672 \
-p 5672:5672 \
--restart=always \
rabbitmq:3.11.19-management
镜像队列
-
目的:解决普通集群环境下高可用的问题
-
原理
- 队列内容通过主从复制同步到多个节点,主节点处理读写请求,从节点实时同步数据
- 主节点故障时,从节点通过选举机制自动接管,服务无感知切换
-
镜像队列虽然实现了高可用,但消息在节点间同步时出现宕机,仍有可能丢失消息
-
加入集群
# Node2/Node3执行 rabbitmqctl stop_app rabbitmqctl reset rabbitmqctl join_cluster --ram rabbit@rabbit1 # Node1为磁盘节点,其他可设为内存节点 rabbitmqctl start_app
-
验证集群状态
rabbitmqctl cluster_status # 输出应包含所有节点,且running_nodes列表完整
-
创建镜像策略
# 将所有队列设置为镜像队列(全量同步) rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'# 或指定队列前缀(如以"mirror_"开头的队列) rabbitmqctl set_policy ha-mirror "^mirror_" '{"ha-mode":"exactly","ha-params":2}'
仲裁队列
-
目的:类似于redis的哨兵机制,进一步减小了消息丢失的风险
-
原理
- 多数派确认:消息需被超过半数节点(如3节点集群需2个确认)持久化后才返回成功响应,确保数据安全
- 选举机制:若Leader宕机,Followers通过Raft协议发起选举,新Leader需获多数节点投票,避免脑裂
-
队列声明与配置
Map<String, Object> arguments = new HashMap<>();
arguments.put("x-queue-type", "quorum"); // 声明为Quorum队列
channel.queueDeclare("test-quorum-queue", true, false, false, arguments);
Streams队列
-
目的:数据分片,进一步提高了传输性能
-
队列声明与配置
Map<String, Object> args = new HashMap<>();
args.put("x-queue-type", "stream"); // 必须设置为stream
args.put("x-max-length-bytes", 20_000_000_000L); // 最大20GB
args.put("x-stream-max-segment-size-bytes", 100_000_000); // 每段100MB
channel.queueDeclare("my-stream", true, false, false, args);