JAVA面试:消息队列
- 项目为何选择MQ?使用场景与重复消费处理
核心价值与场景
- 解耦系统:生产者与消费者独立演化(如订单系统与积分系统,数据分析系统和打标系统,采集消息系统和客户端)。
- 异步处理:耗时操作(如短信通知,批量操作:批量打标、批量删除、客户人群计算)异步化,提升主流程响应速度。
- 削峰填谷:应对瞬时高并发(如秒杀场景),通过MQ缓冲请求。
- 事务一致性:订单支付后扣减库存(事务消息保障最终一致性)。
重复消费解决方案 - 业务幂等性设计:
- 唯一业务ID:如数据库唯一索引、Redis分布式锁(Redisson)。
- 状态机控制:订单状态仅允许特定操作执行一次。
- RocketMQ原生机制:
- 消息Key+Check:生产者设置唯一Key,消费者查询Redis是否存在该Key。
- 手动提交Offset:消费成功后手动ACK,避免宕机导致重复拉取。
- RocketMQ底层存储机制
核心存储结构
- CommitLog:全局顺序写入的物理文件,文件名表示起始偏移量(如
0000000000000000000),所有Topic消息混洗存储,利用顺序写提升吞吐量。 - ConsumeQueue:逻辑队列,存储消息在CommitLog的偏移量、大小及Tag哈希,类似“索引文件”,加速消费检索(每条20字节)。
- IndexFile:基于消息Key或时间的稀疏索引,支持快速查询(如通过
messageId定位消息)。
- 零丢失与消息不重复保障
零丢失策略
- 生产者端:
- 同步发送+重试:设置
retryTimesWhenSendFailed=3,失败后重试其他Broker。 - 事务消息:半消息(Half Message)暂存HALF队列,本地事务提交后二次确认。
- 同步发送+重试:设置
- Broker端:
- 同步刷盘:
flushDiskType=SYNC_FLUSH,消息写入磁盘后返回ACK。 - 主从强同步:
brokerRole=SYNC_MASTER,主从均确认后才返回成功。
- 同步刷盘:
- 消费者端:
- 手动ACK:消费成功后返回
CONSUME_SUCCESS,失败则RECONSUME_LATER触发重试。 - 死信队列(DLQ):超过16次重试后转入DLQ,人工介入处理。
- 手动ACK:消费成功后返回
- 线上MQ常见问题
- RocketMQ
- 消息积压:消费者处理速度<生产速度,需扩容实例或优化消费逻辑。
- Rebalance风暴:频繁消费者上下线触发队列重分配,优化
rebalanceWaitTimeMills延长间隔。 - 主从同步延迟:网络抖动导致同步超时,检查
broker.conf同步参数。 - kafka
-
消息积压处理
- RabbitMQ与RocketMQ核心差异
| 维度 | RocketMQ | RabbitMQ |
|---|---|---|
| 存储模型 | CommitLog+ConsumeQueue混合存储 | 内存+磁盘混合,支持镜像集群 |
| 事务支持 | 原生事务消息(两阶段提交) | 依赖插件或外部事务管理 |
| 顺序消息 | 全局/分区顺序支持 | 仅队列内部顺序 |
| 吞吐量 | 同步刷盘约10万TPS | 万级TPS(依赖镜像模式) |
| 适用场景 | 金融交易、高吞吐场景 | 路由复杂、低延迟场景 |
- 幂等性与零丢失实现
- 幂等性:
- 数据库唯一索引:拦截重复业务键。
- Redis幂等令牌:消费前
SETNX锁,成功则处理。
- 零丢失:
- Dledger副本:基于Raft协议自动切换主节点。
- Checkpoint机制:记录刷盘时间戳,故障恢复时重放日志。
- 选择RocketMQ而非Kafka的原因
- 事务与顺序需求:金融场景依赖事务消息与严格顺序。
- 企业级支持:阿里云提供全链路监控与故障自愈。
- 灵活过滤:支持SQL表达式过滤(如
a > 5 AND b = 'hello')。
- 确保消息不重复的机制
- 生产者去重:全局SequenceId+本地缓存。
- 消费者幂等:数据库乐观锁(版本号控制)。
- 消息积压处理
- 扩容Consumer:增加实例数至Queue数量一致。
- 批量消费:调整
maxBatchSize提升吞吐量。
- 消息重复根源
- 网络波动导致生产者重试。
- 消费者处理超时触发Broker重投。
- 主从切换后未同步消息。
- Rebalance流程与触发
- 触发条件:消费者上下线、队列数变更。
- 分配策略:平均分配队列(如10队列→3消费者分配3-4-3)。
- 文件存储与CommitLog映射
- CommitLog:消息按顺序追加到1GB文件,文件名标识起始偏移量。
- ConsumeQueue:每条记录CommitLog偏移量、消息大小及Tag哈希,通过逻辑偏移定位消息。
- NameServer功能
- 路由管理:维护Topic→Broker映射表,客户端定时拉取(30秒)。
- 故障剔除:Broker 30秒无心跳则从路由表移除。
- RocketMQ核心特性
- 高吞吐:顺序写+内存映射(Mmap)减少I/O损耗。
- 灵活过滤:支持SQL表达式与Tag哈希过滤。
- 多副本高可用:Dledger基于Raft协议实现自动主从切换。
- 企业级监控:提供Dashboard与Prometheus指标集成。
总结
RocketMQ通过事务消息+同步刷盘+主从同步+手动ACK组合实现零丢失,结合幂等性设计+Rebalance优化保障消息可靠。其混合存储模型与企业级事务支持使其在金融、电商等强一致性场景优于Kafka。实际部署需根据业务SLA权衡性能与可靠性(如同步刷盘降低吞吐量)。

浙公网安备 33010602011771号