【Java面试】RocketMQ是如何做到零消息丢失的?

一、生产阶段:确保消息可靠发送

  1. 同步发送与重试机制

    • 生产者采用同步发送send()方法)并等待Broker返回SendResult,仅当状态为SEND_OK(刷盘和主从同步均成功)时确认发送成功。
    • 默认同步重试3次,可通过setRetryTimesWhenSendFailed(10)调整重试次数,应对网络抖动等问题。
  2. 事务消息机制

    • Half消息:生产者先发送半消息到Broker的HALF队列(对消费者不可见),Broker确认接收后回调生产者执行本地事务。
    • 事务状态检查:若本地事务结果未明确(如超时),Broker会通过回调接口checkLocalTransaction补偿查询,最终提交(COMMIT)或回滚(ROLLBACK)消息。
    • 该机制确保本地事务与消息发送的原子性,避免因网络或Broker故障导致消息丢失。

二、存储阶段:高可用持久化

  1. 同步刷盘与主从同步

    • 刷盘策略:配置flushDiskType=SYNC_FLUSH,消息写入内存后立即同步刷盘,绕过PageCache直接持久化到磁盘。
    • 主从复制:设置brokerRole=SYNC_MASTER,Master需等待Slave同步完成才返回成功,防止主节点宕机导致数据丢失。
  2. 存储结构设计

    • CommitLog:顺序写入消息二进制数据,文件默认1GB,循环生成确保高性能。
    • ConsumeQueue/IndexFile:逻辑索引文件(固定大小20MB/400MB),通过稀疏索引快速定位消息,支持故障恢复。

三、消费阶段:可靠消费与重试

  1. 手动提交Offset

    • 消费者需显式返回CONSUME_SUCCESS,Broker才会更新消费进度。若处理失败返回RECONSUME_LATER,触发重试机制。
  2. 重试与死信队列

    • 消费失败的消息会进入延时队列,按延时等级(如1s、5s、10s)重试,超过最大重试次数(默认16次)则转入死信队列,供人工处理。

四、容灾与监控

  1. 集群高可用

    • 多Master多Slave部署,结合NameServer集群(AP设计)管理路由,避免单点故障。
    • Broker定期心跳检测(10s间隔),超时120s剔除故障节点。
  2. 补偿与降级

    • 极端情况下(如全集群宕机),可将消息暂存本地数据库或缓存,待恢复后重新投递。
    • 监控系统实时跟踪消息状态,异常时触发告警。

总结

RocketMQ通过事务消息+同步刷盘+主从同步+手动提交+重试机制的组合,实现从生产到消费的全链路零丢失。实际应用中需根据业务权衡性能与可靠性(如同步刷盘降低吞吐量),必要时结合本地消息表等业务层方案增强保障。

你可能感兴趣的:(【Java面试】RocketMQ是如何做到零消息丢失的?)