RabbitMQ学习笔记-消息可靠保障与系统稳定
在企业级应用中“消息不丢失、处理不重复、系统抗故障”是核心诉求。RabbitMQ提供了一系列高级特性保障消息传输的可靠性和系统的稳定性。1、消息可靠性保障要确保消息不丢失需同时开启“持久化三件套”和“双重确认机制”形成全链路可靠保障。还需要避免消息乱序和重复。1.1、 持久化持久化的核心是将数据写入硬盘避免服务器重启后数据丢失。需同时配置以下三点交换机持久化声明交换机时设置durabletrue重启后交换机仍存在。队列持久化声明队列时设置durabletrue重启后队列仍存在但队列中的消息需额外配置持久化。消息持久化发送消息时设置delivery_mode2AMQP协议规定消息会被写入硬盘。注意三个步骤缺一不可。例如仅持久化队列而未持久化消息重启后队列存在但消息丢失。1.2、 双重确认机制通过“生产者确认”和“消费者确认”确保消息从发送到处理的全链路可靠。生产者确认Publisher Confirm生产者发送消息后RabbitMQ会通过信道返回ACK消息已接收并持久化或NACK消息接收失败。生产者可通过监听确认信号实现失败重试或日志记录。 示例逻辑开启确认模式后发送消息时添加确认监听器若收到NACK则间隔1秒重试重试3次失败后记录到错误日志。消费者确认Consumer Ack消费者处理消息后需显式发送ACK信号RabbitMQ收到后才删除消息若未发送ACK如消费者宕机消息会重新入队这里可能导致消息重复若处理失败可发送NACK并指定是否重新入队。 注意避免使用自动ACKAutoAcktrue否则消费者拿到消息后立即确认若后续处理失败消息已被删除导致数据丢失。1.3、消息避免乱序原因生产者把顺序相关的消息发到同一个队列但消费者是多线程并发消费处理速度不同导致顺序错乱。解决方案强制串行只启动一个消费者单线程消费消息按入队顺序逐个处理。吞吐量低。分区顺序使用它内置插件根据请求的特征如用户ID计算哈希值让相同特征消息进入同一队列。队列绑定的每个消费者内部存ID做分组排队让相同ID的消息串行处理不同ID的并行。业务层排序每条消息带一个序号消费者收到后先检查序号如果序号等于当前序号则处理小于则丢弃大于则等待直到按顺序补齐。1.4、消息避免重复原因消费者因为处理超时或者网络中断等导致没有发ACK确认导致RabbitMQ认为消费失败重新投递消息。解决方案数据库唯一约束比如订单消息用消息id作为唯一键插入消息表处理前检查消息id是否存在。业务状态机比如订单状态从1→2更新时加条件update...set status2 where status1。Redis分布式锁消费前用SETNX加锁加锁成功才设置redis标记位并处理业务过期时间设长一些。重复消息来时如果标记存在就不处理。2 死信队列DLX死信队列Dead Letter Exchange是专门处理“异常消息”的队列当消息满足以下条件时会被标记为“死信”并路由到死信队列消息被消费者拒绝basicReject/basicNack且未设置重新入队requeuefalse消息在队列中存活时间超过TTL消息超时时间队列达到最大长度新消息无法入队。死信队列配置步骤声明死信交换机如dlx-exchange类型可任意常用Direct声明死信队列如dlx-queue并绑定到死信交换机给正常队列设置死信参数x-dead-letter-exchange死信交换机名称x-dead-letter-routing-key死信路由键x-message-ttl消息超时时间如30分钟单位毫秒。由于死信队列可以配置交换机并绑定不同队列因此可以让不同类型的死信进入不同的队列。适用场景电商订单30分钟未支付自动取消、物流轨迹超时未更新告警、异常消息人工复盘等。3 延迟队列RabbitMQ本身不直接支持延迟队列但可通过“TTL死信队列”间接实现给消息设置TTL到期后成为死信自动路由到死信队列消费者监听死信队列即可实现定时任务。适用场景订单30分钟未支付自动取消用户注册后24小时未登录发送召回通知物流包裹超时未签收触发客服跟进。4、镜像队列与集群单节点RabbitMQ存在单点故障风险企业级部署需构建集群并配置镜像队列确保节点宕机后服务不中断。4.1、 镜像队列将队列数据同步到多个节点副本主节点处理消息从节点实时同步数据。当主节点宕机从节点自动升级为主节点继续提供服务。核心配置通过CLI命令# 给所有order开头的队列配置镜像队列复制到所有节点自动同步rabbitmqctl set_policy ha-all ^order- {ha-mode:all,ha-sync-mode:automatic}4.2、分布式集群多节点组成逻辑集群通过Erlang分布式协议同步元数据队列、绑定关系等结合负载均衡分摊消息处理压力。在K8s环境中可通过RabbitMQ Operator实现集群自动扩缩容和故障转移。5 流量控制避免消费者过载当生产者发送消息速度超过消费者处理速度时会导致队列积压。RabbitMQ通过以下机制实现流量控制basicQos限流消费者通过basicQos(prefetchCountN)设置每次预取的消息数量即消费者同时处理N条消息处理完并确认后再获取下一批避免同时处理过多消息导致过载。背压机制当队列积压过多或消费者处理过慢时RabbitMQ会暂停向消费者发送新消息直至消费者确认部分消息缓解消费者压力。注意这里的流量控制只是为了保护消费者端如果生产者端消息来临的速度大于消费者处理速度队列会持续积压多的消息要么ttl到期进入死信、要么占满磁盘触发系统保护。