面试题答案
一键面试确保消息不丢失
- 生产者端
- 同步发送与确认机制:使用同步发送消息方式,生产者等待Broker返回确认消息发送成功的响应。例如在Java中,使用
DefaultMQProducer
的send
方法发送消息,若返回状态为SEND_OK
,则表示消息成功发送到Broker。 - 事务消息:对于一些需要保证最终一致性的场景,使用事务消息。生产者先发送半消息到Broker,Broker返回成功后,生产者执行本地事务,根据本地事务执行结果决定提交或回滚半消息。比如在电商下单场景,下单成功后再提交事务消息,确保消息与业务操作的一致性。
- 同步发送与确认机制:使用同步发送消息方式,生产者等待Broker返回确认消息发送成功的响应。例如在Java中,使用
- Broker端
- 刷盘策略:采用同步刷盘策略,确保消息在写入内存的同时,同步写入磁盘。在
broker.conf
配置文件中,设置flushDiskType = SYNC_FLUSH
,这样即使Broker发生故障,已成功写入的消息不会丢失。 - 主从复制:配置多台从Broker,主Broker将消息同步复制到从Broker。可以采用同步复制或异步复制,同步复制能更好地保证消息不丢失,但性能略低;异步复制性能高,但可能存在短暂的消息丢失风险。在
broker.conf
中配置brokerRole = SYNC_MASTER
或ASYNC_MASTER
来设置主从复制模式。
- 刷盘策略:采用同步刷盘策略,确保消息在写入内存的同时,同步写入磁盘。在
- 消费者端
- 手动确认机制:消费者采用手动确认消费模式,确保在处理完消息业务逻辑后,再向Broker发送确认消息。在Java中,使用
DefaultMQPushConsumer
设置acknowledgeMode = AcknowledgeMode.MANUAL
,处理完消息后调用consumer.commitSync()
方法进行确认。
- 手动确认机制:消费者采用手动确认消费模式,确保在处理完消息业务逻辑后,再向Broker发送确认消息。在Java中,使用
确保不重复消费
- 消息唯一标识:生产者在发送消息时,为每条消息设置唯一的标识,如使用UUID。消费者在消费消息时,先根据这个唯一标识判断消息是否已消费过。
- 消费幂等性:设计消费者业务逻辑时保证幂等性。例如在数据库操作中,使用
INSERT INTO... ON DUPLICATE KEY UPDATE
语句,多次执行相同的插入操作不会产生重复数据;在更新操作中,先查询数据状态,根据当前状态判断是否需要更新,避免重复更新。
服务快速恢复
- 主从切换:当主Broker发生故障时,从Broker能快速切换为主Broker继续提供服务。RocketMQ支持自动主从切换,通过选举算法(如Raft算法)选出新的主Broker。配置多个NameServer,NameServer之间相互注册,保持数据一致性,当某个NameServer发生故障时,其他NameServer仍能提供服务,确保Broker信息的正常获取。
- 节点监控与报警:使用监控工具(如Prometheus + Grafana)对Broker集群进行实时监控,监控指标包括消息堆积量、CPU使用率、内存使用率等。当指标超过阈值时,及时发送报警信息,运维人员可以快速响应,处理故障节点。
- 自动故障检测与恢复:Broker自身具备故障检测机制,如心跳检测。Broker定期向NameServer发送心跳包,NameServer通过心跳检测Broker的存活状态。当发现Broker无心跳时,标记该Broker为故障状态,并触发主从切换等恢复流程。