当前位置: 首页 > news >正文

java面试:mq 优化

消息队列,简单说就是在分布式系统里加了一个“靠谱的中间人”,让系统之间不直接喊话,而是通过发消息来异步协作。

在银行核心系统干了这几年,我对 MQ 的理解是:它不只是个工具,更是一种架构设计思想——用暂时的“不一致”换取系统整体的高可用和高吞吐。下面我结合真实场景跟你详细聊聊。


一、解耦:让核心系统“喘口气”

在没有 MQ 之前,比如贷款放款成功后,需要做一堆事:通知风控系统更新额度、给营销系统发短信、触发监管上报、同步数据到大数据平台等等。如果直接 RPC 调用,放款接口就得串行等所有这些下游返回,响应时间拉长不说,任何一个下游挂了都会导致放款失败,这是不能接受的。

引入 MQ 后,核心系统只需要做两件事:完成放款+发一条“放款成功”的消息。至于谁要消费这条消息、消费方是死是活,核心系统根本不用关心。这样,核心链路被保护得干干净净。

二、异步:把“快慢”分开,提升响应速度

银行业务有些操作非常耗时,比如生成一份几十页的贷款合同 PDF、跑反洗钱检查。如果用户提交申请后要等 5 秒才能看到结果,体验会很差。用 MQ,我们可以把必须同步完成的校验先做完,把耗时操作扔到后台慢慢处理。用户立刻能看到“申请已受理”,后台慢慢跑,处理完了再通知用户。这就做到了快速响应和复杂处理的兼顾

三、削峰填谷:抵御交易洪峰

每年国债发行、双十一大促,银行系统的交易量会瞬间翻几十倍。如果硬扛,数据库连接池会被瞬间打满,导致雪崩。有了 MQ,后端服务就可以按照自己的处理能力,平滑地从队列里拉取消息。MQ 就像一个水库,上游洪水涌来先蓄起来,下游按固定的流量慢慢放。这保护了我们脆弱的数据库和核心账务系统。

举个例子:我们行的批量代扣业务,发薪日千万级交易进来,全部先进 MQ,扣款服务按每秒 5000 笔的速度消费,平稳处理一两个小时,系统一直稳稳当当。

四、最终一致性的“润滑剂”

你之前做过分布式事务,知道强一致性(TCC/Seata AT)成本很高、性能受限。但在很多场景(比如积分累计、通知发送),我们其实不需要那么强的一致性,只要保证最终一致就行。MQ 配合本地消息表,就是一种经典的最终一致性方案。核心系统扣款成功,同时往本地数据库插一条流水和发一条消息,后台再异步通知下游,失败了就重试,直到下游确认成功。牺牲毫秒级的实时性,换来系统级的简单可靠

五、顺序保证与数据分发

像银行的对账系统,要求数据必须按顺序处理,否则账户余额会乱。MQ 的分区有序机制,可以把同一笔订单的操作按序发给同一个消费者,保证严格顺序。同时,一条消息还可以被多个下游系统订阅(消息广播),一份数据,多个消费方各自处理,效率拉满。


⚠️ 银行场景下用 MQ 要特别注意的事 ## 面试回答核心话术(可直接用于面试)

“RabbitMQ 的优点主要有四个:第一,可靠性极高,它支持消息持久化、生产者确认、消费者手动 ACK,能保证消息不丢失;第二,功能完备,有丰富的交换机类型(direct、topic、fanout、headers)和灵活的路由机制,能满足各种业务场景;第三,插件生态强,自带管理后台、延迟队列插件、监控插件,运维方便;第四,社区成熟,文档全、案例多,遇到问题容易找到答案。

缺点也有几个:吞吐量相对较低,因为 RabbitMQ 走的是 AMQP 协议,每条消息都要经过交换机和队列两层路由,单机 TPS 在万级,不如 Kafka 的百万级;内存型架构,大量消息堆积时会吃内存,影响性能;语言依赖,底层用 Erlang 开发,团队如果想二次开发门槛较高;不支持消息回溯,消息一旦被消费确认就删除了,不像 Kafka 那样支持按 offset 回放。

在银行系统中,我们对可靠性要求极高,核心交易的通知、对账、监管上报这些链路都用 RabbitMQ;但像日志收集、实时流处理这种高吞吐场景,我们会选 Kafka。选型的关键是根据业务对可靠性和吞吐量的权衡。”


详细解析

一、RabbitMQ 的优点

1. 可靠性高,消息不丢
  • 生产者确认publisher-confirm机制,消息成功写入磁盘后 Broker 返回 ack,否则重发。
  • 持久化:队列(durable)和消息(persistent)都设置为持久化,Broker 重启不丢。
  • 消费者手动 ACK:处理完成后再确认,失败可 nack 重发。
  • 银行实践:核心交易通知、对账报文全部开启这三层保障。
2. 功能完备,路由灵活
  • 四种交换机:
    • Direct:精确匹配路由键,适合点对点。
    • Topic:通配符路由(*.orange.*),适合主题订阅。
    • Fanout:广播,适合配置更新、群发通知。
    • Headers:基于消息头匹配,较少用。
  • 死信队列:处理失败的消息自动转入,便于人工兜底。
  • 延迟队列:通过 TTL + 死信实现,或使用rabbitmq_delayed_message_exchange插件。
  • 优先级队列:按优先级分发。
3. 插件生态强,运维方便
  • 管理后台rabbitmq_management插件,可看队列积压、消费速度、连接数。
  • 监控集成:Prometheus + Grafana 通过rabbitmq_prometheus采集。
  • 延迟插件:比 TTL+死信更精确。
4. 社区成熟,文档全
  • 大量 Java 客户端(Spring AMQP、RabbitTemplate)支持,配置简单。

二、RabbitMQ 的缺点

1. 吞吐量相对较低
  • AMQP 协议复杂,每条消息需经过交换机和队列两层路由。
  • 单机 TPS 约万级,远低于 Kafka 的百万级。
  • 不适合:海量日志、实时流计算、大数据管道。
2. 消息大量堆积时性能下降
  • 消息堆积时会大量占用内存,可能触发流控(Flow Control)阻塞生产者。
  • 建议设置队列的max-length或 TTL 限制。
3. Erlang 开发语言门槛
  • RabbitMQ 使用 Erlang 开发,源码阅读和二次开发门槛高,一般只能运维层面调优。
4. 不支持消息回溯
  • 消息一旦被消费者 Ack,立即删除,无法重复消费历史消息。
  • 对比 Kafka 的 offset 回溯和重放,RabbitMQ 需要额外设计补偿机制。
5. 集群模式有局限
  • 镜像队列(Mirror Queue)能保证高可用,但同步延迟和网络开销大。
  • 仲裁队列(Quorum Queue,3.8+)基于 Raft 协议,可靠性高但性能更低。

三、银行系统中的选型对比

场景推荐 MQ理由
核心交易通知、对账、监管上报RabbitMQ可靠性第一,吞吐量要求不高
日志收集、审计、大数据分析Kafka高吞吐、支持回溯、磁盘顺序读写
分布式事务消息RocketMQ阿里生态,支持事务消息和顺序消息
内部异步解耦、任务分发RabbitMQ 或 RocketMQ两者均可,看团队熟悉度

我们行的实践

  • 贷款放款成功后的通知(营销、风控、监管)走 RabbitMQ,配置了持久化、手动 ACK、死信队列。
  • 交易日志流水采集走 Kafka,一天几十亿条消息,用 Flink 实时消费。
  • 分布式事务(TCC/SAGA)的通知和补偿走 RocketMQ 的事务消息。
  • 消息绝对不能丢:必须打开生产者 Confirm、队列持久化、消费者手动签收(ACK),我们之前就因为一个参数没配好,丢了几笔交易消息,对账发现后才补齐。
  • 幂等处理是铁律:消费端必须用业务唯一键(如交易流水号)做幂等控制,MDB 里有唯一索引是最后防线。网络抖动时 MQ 会重复投递,没做幂等的话资金就会出错。
  • 不要用 MQ 处理实时资金交易:转账请求绝对不能先进 MQ,否则用户看不到即时结果。MQ 负责旁路、通知、数据同步,核心资金链路还是走 RPC/同步调用。

总结一句话:MQ 是分布式系统的“神经中枢”,它让核心链路能护住自己,让非核心链路放开手脚,并通过削峰和最终一致性,为金融系统提供了一道关键的弹性防线。
问题:RabbitMQ 如何保证消息不丢失?

面试回答核心话术(可直接用于面试)

“RabbitMQ 保证消息不丢失,我从生产者、Broker、消费者三个环节来回答。

生产者端,我开启Publisher Confirm 确认机制。消息发送后,必须等待 Broker 返回 ack 确认才算发送成功。如果返回 nack 或者超时未确认,就进行重发。同时把消息投递模式设为PERSISTENT_TEXT_PLAIN,保证消息本身是可持久化的。

Broker 端,我做了双重保障。一是把队列声明为durable 持久化,Broker 重启后队列元数据不丢;二是把消息投递模式设为持久化,写入磁盘后才返回确认。如果追求更高可靠性,还可以用镜像队列仲裁队列(Quorum Queue),把数据同步到多个节点,单节点故障也不丢。

消费者端,我关闭自动确认,采用手动 ACK。必须在消息真正处理完成、数据库事务提交之后,才调用basicAck确认。如果处理失败,调用basicNack让消息重新入队或者进入死信队列。千万不能在业务处理之前就确认,否则确认了但业务没成功,消息就真丢了。

在银行项目里,我们核心交易通知链路就配置了这三层保障:spring.rabbitmq.publisher-confirm-type=correlated+ 持久化队列 +acknowledge-mode=manual。上线至今没有发生过消息丢失的事故。”


详细解析

一、整体架构图

生产者 Broker 消费者 │ │ │ │──①发送消息──────────→│ │ │ │──②持久化到磁盘──────→│ │ │ │ │←③返回ack/nack───────│ │ │ │ │ │ │──④推送消息──────────→│ │ │ │──⑤处理业务 │ │ │──⑥手动ACK │ │←⑦ACK确认────────────│

二、生产者端:Confirm 机制 + 消息持久化

1. Publisher Confirm
// Spring Boot 配置spring:rabbitmq:publisher-confirm-type:correlated// 开启确认回调

工作原理

  • 生产者发送消息后,Broker 在消息写入磁盘后回调confirmCallback
  • 如果返回ack=true,消息成功到达;如果ack=false或超时,触发重发逻辑。

代码案例

@PostConstructpublicvoidinitConfirmCallback(){rabbitTemplate.setConfirmCallback((correlationData,ack,cause)->{if(ack){log.info("消息成功投递,ID: {}",correlationData.getId());// 更新本地消息表状态为已发送}else{log.error("消息投递失败,原因: {}",cause);// 重发 或者 落库等待定时任务补偿}});}
2. 消息持久化标识
// 发送时设置投递模式为持久化MessagePropertiesprops=newMessageProperties();props.setDeliveryMode(MessageDeliveryMode.PERSISTENT);Messagemessage=newMessage(body,props);rabbitTemplate.send(exchange,routingKey,message);

三、Broker 端:队列持久化 + 消息持久化

1. 队列声明为 durable
@BeanpublicQueueorderQueue(){returnQueueBuilder.durable("order.queue").build();// durable=true}
2. 镜像队列(高可用)
# 策略定义:所有节点上都有这个队列的镜像rabbitmqctl set_policy ha-all "^order\." '{"ha-mode":"all"}'

缺点:所有节点都同步,网络开销大,性能下降。

3. 仲裁队列(Quorum Queue,3.8+ 推荐)
@BeanpublicQueueorderQueue(){returnQueueBuilder.durable("order.queue").quorum()// 使用 Raft 协议,过半节点确认即持久化.build();}

优势:基于 Raft 协议,数据安全性更高,主节点宕机自动切换。


四、消费者端:手动 ACK + 业务幂等

1. 配置手动确认
spring:rabbitmq:listener:simple:acknowledge-mode:manual // 手动确认prefetch:1 // 每次只取一条,保证公平分发
2. 正确的手动 ACK 流程
@RabbitListener(queues="order.queue")publicvoidhandle(Messagemessage,Channelchannel)throwsIOException{StringorderId=message.getMessageProperties().getMessageId();try{// 1. 业务处理(写数据库)orderService.process(orderId);// 2. 业务成功后才确认channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);}catch(Exceptione){log.error("消息处理失败: {}",orderId,e);// 3. 失败则重新入队,或转入死信队列channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);}}

关键点

  • basicAck的第二个参数multiple是否批量确认,一般设false
  • basicNack的第三个参数requeue是否重新入队,true则放回队列重试,false则丢弃或进入死信队列。
3. 死信队列兜底

重试次数过多仍失败的消息,转入死信队列,人工处理:

@BeanpublicQueuedeadLetterQueue(){returnQueueBuilder.durable("dead.letter.queue").build();}

五、银行生产环境的完整配置

spring:rabbitmq:host:rmq-bank-core.example.comport:5672username:bank_userpassword:${RABBITMQ_PASSWORD}# 生产者确认publisher-confirm-type:correlatedpublisher-returns:true# 消息无法路由到队列时回调# 消费者手动确认listener:simple:acknowledge-mode:manualprefetch:250# 批量拉取,平衡吞吐和公平retry:enabled:false# 关闭 Spring 重试,由业务自己控制

监控指标

  • rabbitmq_queue_messages_ready:队列待消费消息数
  • rabbitmq_queue_messages_unacknowledged:已投递但未确认的消息数
  • 告警规则:unacknowledged 消息持续增长超过 5 分钟,立即排查消费者是否故障。

六、总结三环节防丢

环节机制配置
生产者Publisher Confirmpublisher-confirm-type: correlated
Broker队列 + 消息持久化 / 镜像 / 仲裁队列durable=true/quorum()
消费者手动 ACKacknowledge-mode: manual+ 业务完成后确认

问题:RabbitMQ 如何解决消息重复和消息堆积?

面试回答核心话术(可直接用于面试)

“这两个问题分别对应消费端幂等消费能力与容量规划,我分开来说。

消息重复的根源在于网络波动或消费者宕机导致 Broker 未收到 ACK,从而重新投递。解决办法是消费者必须实现幂等。我们会在消息体里携带全局唯一业务流水号,消费端先查 Redis 或数据库判断该流水号是否已处理,处理过则直接 ACK 跳过;未处理则执行业务,成功后把流水号记入 Redis 并写数据库唯一约束兜底。这样即使同一条消息投递多次,业务也只会执行一次。

消息堆积通常是因为消费者处理能力跟不上生产速度,或者消费者出了故障。我分预防和应急两类措施。预防上,消费者端我会优化业务逻辑、批量处理、合理设置 prefetch 并发数;队列层面设置最大长度或 TTL,避免无限堆积。应急情况下,可以紧急增加消费者实例,但要注意不能超过队列分区数;如果实在来不及消费,就写一个临时转发程序,把积压消息快速转储到另一个队列或数据库,等修复后慢慢回灌。监控上,我们对messages_ready设置告警,超过阈值立刻介入,避免雪崩。

在银行项目中,我们线上所有核心队列都配置了死信队列 + 幂等 + 积压告警,曾遇到过批量扣款消息堆积,通过临时扩容消费者和优化 SQL 把积压从 200 万条降到 0,整个过程没有丢一条消息。”


详细解析

一、消息重复 → 消费端幂等

1. 重复消息的原因
  • 网络抖动:Broker 推送消息后,消费者已处理但 ACK 未到达 Broker,Broker 超时重发。
  • 消费者宕机:消费者刚拉取消息还未处理就挂了,Broker 重新投递给其他消费者。
  • 客户端重试:Spring AMQP 的 retry 机制开启后,内部重试会造成同一消息多次进入监听器。
2. 幂等方案设计

核心思想:每条消息携带唯一业务 ID,消费端用“查-处理-记”的模板保证只执行一次

消息发送方(生产者):

MessagePropertiesprops=newMessageProperties();StringbizId=UUID.randomUUID().toString();// 全局唯一流水号props.setMessageId(bizId);Messagemessage=newMessage(payload,props);rabbitTemplate.send(exchange,routingKey,message);

消费方

@RabbitListener(queues="order.queue")publicvoidhandle(Messagemessage,Channelchannel)throwsIOException{StringbizId=message.getMessageProperties().getMessageId();// 1. 查:用 Redis 或 DB 判断是否已处理Booleanprocessed=redisTemplate.opsForValue().setIfAbsent("msg:"+bizId,"1",10,TimeUnit.MINUTES);if(Boolean.FALSE.equals(processed)){channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);return;// 已处理,直接确认}try{// 2. 处理业务(数据库事务)orderService.process(bizId,message.getBody());// 3. 成功确认channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);}catch(Exceptione){// 失败则删除幂等标记,让下次重试可以重新处理redisTemplate.delete("msg:"+bizId);channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);}}

双保险:数据库里加唯一索引UNIQUE KEY uk_biz_id (biz_id),即使 Redis 挂了,数据库也能拦截重复写入。


二、消息堆积 → 容量规划 + 紧急处理

1. 堆积原因分析
  • 生产 > 消费:日常流量预估不足,消费者处理不过来。
  • 消费者故障:代码 bug、第三方超时、数据库慢查询导致消费者卡死。
  • 消费端限流不当prefetch值太小,消费者大量时间花在等待新消息上。
2. 预防措施(平时做好)
  • 消费者并发
    spring:rabbitmq:listener:simple:concurrency:5# 初始 5 个消费线程max-concurrency:10# 最大 10 个消费线程prefetch:250# 每个线程一次拉取 250 条
  • 队列容量限制
    @BeanpublicQueueorderQueue(){returnQueueBuilder.durable("order.queue").maxLength(100000)// 队列最多存 10 万条.overflow(Overflow.rejectPublish)// 溢出时拒绝发布.build();}
  • 消息 TTL:对时效性要求高的消息,设置x-message-ttl,过期自动移入死信队列,避免无用堆积。
3. 应急处理(线上已堆积)
  • 紧急扩容消费者:快速部署新实例,利用队列的并发消费能力提升吞吐。注意,RabbitMQ 的队列是单线程顺序分发,增加消费者能线性提升消费速度。
  • 临时转发:写一个简单消费者,不做业务,只把消息快速转发到另一个容量更大的队列或写入数据库,让原队列压力下降。
  • 服务降级:如果堆积因为下游依赖超时,开启熔断降级,消费者直接返回失败并转入死信队列,保留现场后续补处理。
  • 批量处理:如果业务允许,消费者改为批量拉取、批量入库,减少网络和数据库交互次数。
4. 监控告警
  • rabbitmq_queue_messages_ready:队列待消费消息数,设置阈值(如 5 万)告警。
  • rabbitmq_queue_messages_unacknowledged:已投递未确认数,若持续增长说明消费者处理卡顿。
  • 配合 Grafana 图表,可一眼看出积压趋势。

三、死信队列的兜底作用

对于重试多次仍失败的消息、过期消息、队列满溢出消息,统一转入死信队列,人工排查后重新投递或订正数据。

@BeanpublicQueuedeadLetterQueue(){returnQueueBuilder.durable("dead.letter.queue").build();}

四、银行项目中的实战组合

机制用途实现
全局唯一 bizId幂等去重生产端生成 UUID,消费端 Redis setIfAbsent
DB 唯一索引幂等兜底UNIQUE KEY uk_biz_id (biz_id)
并发消费 + prefetch提升吞吐concurrency: 5, prefetch: 250
队列长度限制 + 死信防无限堆积maxLength + overflow reject + DLQ
积压告警及时发现messages_ready > 50000告警
应急转发程序紧急清积压临时消费者快速转储消息
问题:MQ 的性能优化有哪些选项?

面试回答核心话术(可直接用于面试)

“MQ 性能优化我从生产者、Broker、消费者、网络与系统四个维度来做。

生产者端,核心是减少网络往返和磁盘写入开销。我会开启批量发送(如 RabbitTemplate 的批量消息),启用消息压缩减少带宽占用,并根据业务需要选择异步 Confirm 模式而非同步等待。对于非关键通知,还会适当放松持久化要求以换取更高吞吐。

Broker 端,主要是队列架构和持久化策略的选择。写多读少的场景用仲裁队列代替镜像队列,因为它基于 Raft 多数派写盘,性能更稳;读写频繁的队列我会设置x-queue-mode: lazy,让消息尽量落盘减少内存压力。持久化方面,关键业务必须开启,但非关键日志类消息可以关闭持久化,性能提升非常明显。此外,流控阈值、文件描述符限制、内存水位都要调优。

消费者端,是优化最密集的地方。我会调大prefetch值让消费者批量拉取消息,开启并发消费(concurrency),并将自动确认改为手动批量确认(一次确认多条)。业务层面,把耗时操作(如写库、RPC调用)改为异步或批量处理,避免消费者线程被阻塞。

网络与系统层,主要是缩短生产者、Broker、消费者之间的网络路径(同机房部署),使用高性能磁盘(SSD),JVM 参数调优(堆内存、GC 策略)。

在银行项目中,我们的核心交易通知链路要求高可靠,持久化全开,但通过lazy队列和并发消费,单机吞吐达到 3 万 TPS;而对于日志采集这类非关键场景,我们直接关闭持久化,吞吐量提升到 10 万+。性能优化一定要先明确可接受的可靠性级别,再决定优化方向,两者是权衡关系。”


详细解析

一、生产者端优化

1. 批量发送
// 使用 RabbitTemplate 批量发送List<Message>messages=buildMessages();rabbitTemplate.send(messages);// 内部会批量写入 Socket
  • 效果:减少网络 I/O 次数,降低延迟。
  • 注意:批量不能太大(建议 100~500 条),否则影响实时性。
2. 消息压缩
// 发送前 GZIP 压缩byte[]compressed=compress(body);MessagePropertiesprops=newMessageProperties();props.setContentEncoding("gzip");Messagemsg=newMessage(compressed,props);
  • 效果:节省网络带宽,尤其适合大消息体。
3. 异步 Confirm
// 异步接收确认,不阻塞发送线程rabbitTemplate.setConfirmCallback((correlationData,ack,cause)->{// 异步处理确认结果});
  • 对比:同步 Confirm 会阻塞等待 Broker 返回 ack,吞吐较低;异步模式发送可以流水线化。
4. 适当降低可靠性
  • 非关键消息:关闭 Publisher Confirm,不设持久化,发送后即忘。
  • 可丢失消息(如监控指标):不开启 Confirm,不声明持久化队列。

二、Broker 端优化

1. 队列类型与存储策略
  • Lazy Queuex-queue-mode: lazy):消息直接写入磁盘,内存只存少量元数据,适合堆积量大但消费速度慢的场景。
  • Quorum Queue(Raft 组):比镜像队列性能更稳,写盘延迟更低。
@BeanpublicQueueorderQueue(){returnQueueBuilder.durable("order.queue").quorum()// 仲裁队列.build();}
2. 持久化与刷盘策略
  • 关键业务durable=truedelivery_mode=2(持久化消息),确保不丢。
  • 非关键业务:声明非持久化队列,消息也不持久化,磁盘 IO 几乎为零,吞吐量极高。
3. 内存和磁盘阈值
# rabbitmq.conf vm_memory_high_watermark.relative = 0.6 # 内存使用到60%触发流控 disk_free_limit.absolute = 2GB # 磁盘剩余空间低于2GB触发告警
4. 流控(Flow Control)调优
  • 当内存或磁盘达到阈值时,Broker 会阻塞生产者连接。通过提高阈值或扩容解决。
  • 监控命令:rabbitmqctl list_connections查看被阻塞的连接。
5. 文件描述符和 Socket 限制
# /etc/security/limits.conf rabbitmq soft nofile 65536 rabbitmq hard nofile 65536

三、消费者端优化

1. Prefetch 与并发消费
spring:rabbitmq:listener:simple:prefetch:500# 一次预取500条,减少网络交互concurrency:5# 并发线程数max-concurrency:10
  • 原理prefetch控制每次从队列拉取的消息数,增大可减少网络 RTT,但过大会导致消息在消费者侧堆积,可能造成单点故障时大量消息未确认。
2. 批量确认(Multi ACK)
// 每处理 100 条消息,统一确认一次intcount=0;while(count<100){process(msg);count++;}channel.basicAck(lastDeliveryTag,true);// 批量确认
  • 注意:批量确认会跳过中间失败的消息,慎用;建议仍逐条确认,但配合prefetch加大吞吐。
3. 业务逻辑异步化
  • 消息监听器中只做校验、发 MQ、写缓存等轻量操作,耗时逻辑提交给线程池异步处理。
  • 示例:
@RabbitListener(queues="order.queue")publicvoidonMessage(Messagemsg){taskExecutor.submit(()->heavyProcess(msg));channel.basicAck(deliveryTag,false);}
  • 风险:ack 在异步处理前就返回了,若处理失败会丢消息。需采用“先处理再 ack”模式,或结合本地消息表。
4. 避免消费者阻塞
  • 调优数据库连接池大小,减少 SQL 超时。
  • 对第三方 RPC 调用设置合理超时,防止线程卡死。

四、网络与系统层优化

1. 同机房部署
  • 生产者、Broker、消费者尽量在同一数据中心,降低网络延迟。
2. 磁盘性能
  • 使用 SSD 存储 RabbitMQ 数据目录(msg_store_persistent)。
  • 关闭文件访问时间更新(noatime挂载选项)。
3. JVM 调优
  • 堆内存设置不超过系统内存的 60%,留余量给磁盘缓存。
  • GC 选择 G1 或 ParallelGC,避免 CMS 碎片。
RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="+P 1048576 +t 5000000 +stbt db +zdbbl 32000"
  • +P提高最大进程数,+t提高原子操作表。

五、银行场景下的实战组合

场景生产者策略队列类型消费者策略持久化典型吞吐
核心交易通知Confirm + 持久化Quorum 队列手动确认,并发 5全部开启3 万 TPS
日志收集异步发,无 Confirm普通非持久化自动确认,批量拉取关闭10 万+ TPS
批量对账批量发送 + 压缩Lazy 队列手动批量确认开启持久化5 万 TPS
http://www.jsqmd.com/news/1107682/

相关文章:

  • 如何快速解锁加密音乐:免费音频解密工具完整指南
  • 前端/后端/设计师/产品经理学AIGC:2026职场提效与进阶实战指南
  • 如何3分钟掌握Electron asar文件管理:Windows用户的终极图形化解决方案
  • STM32F469II与KMR221实现高精度电压监测方案
  • 仅限内部分享的Git分支治理SOP:某千万级项目迁移IDEA后分支误操作归零的12条硬核纪律
  • 三步实现百度文库文档免费获取:技术原理与实践指南
  • AI训练中的网页爬虫:来源、方法与应用场景
  • AI如何重构App开发流水线:从生成式UI到端侧推理实战
  • Windows 11系统优化终极指南:使用Win11Debloat提升51%性能的完全教程
  • 第一次去医院资料别临时翻
  • 同时管理多个AI供应商的API成本?这份实战指南请收好
  • 西蓝花缩节密植正当时,水肥一体化这套活儿咱给它整明白
  • 【Java转AI实战】第1讲:Java工程师的AI转型地图——你70%的技能已经够用了
  • 混元图像3.0在LiblibAI的本地化落地:即插即用的高确定性AIGC引擎
  • 教育小程序与APP开发避坑指南 + 类型全盘点,千万别踩雷!
  • IDEA中Git冲突无法自动解决?(资深JetBrains认证专家手把手拆解6类顽固冲突根因)
  • 鸿蒙NEXT应用安全实践:服务端证书锁定原理与实现
  • 如何在5分钟内完成Mac Boot Camp驱动的自动化部署?
  • 告别网络限制:tchMaterial-parser让电子课本下载变得如此简单
  • 速卖通首次发布618中国品牌出海成交榜,100大品牌脱颖而出
  • TEKLauncher:方舟生存进化终极启动器 - 告别MOD冲突的完整解决方案
  • 图书借还、逾期罚款核心业务逻辑完整代码讲解
  • 规范更新 Avaya 安全证书,以精细化运维杜绝业务停机隐患
  • AI求职作弊席卷职场,企业“AI打AI”反制,诚实求职者何去何从?
  • 多光标≠简单Ctrl+D,IDEA列编辑模式深度解密:6个被官方文档刻意弱化的生产力核弹功能
  • okbiye 毕业论文 AI 写作实操指南|按页面指引一步到位解决全学段论文撰写难题
  • 自助终端与数字标牌场景解决方案:工业触摸一体机选型指南
  • RSA加解密跨语言实战:Java与JavaScript互操作指南与避坑
  • 掏耳勺可视有必要买吗?可视挖耳勺怎么选?2026全网实测清单
  • 民生服务行业标准化复盘:昆明邦尼到家居家保姆服务合规体系落地实践分析