面试题答案
一键面试生产者角度
- 唯一ID + 本地事务表
- 在发送消息前,生成一个全局唯一ID(例如使用UUID)。
- 将该ID和消息相关信息插入本地事务表,标记消息为待发送状态。
- 发送消息,并使用事务将消息发送操作和本地事务表插入操作绑定。如果消息发送成功,更新本地事务表状态为已发送;若失败,回滚本地事务表插入操作。
- 下次发送相同消息时,先查询本地事务表,若该消息已发送,则不再重复发送。
- 使用MessageId
- RocketMQ在消息发送成功后,会返回一个包含MessageId的SendResult。
- 生产者可以在发送消息前先记录消息的业务关键信息,发送成功后,将MessageId和业务关键信息进行关联存储(如存入缓存)。
- 当需要再次发送相同业务的消息时,根据业务关键信息查询缓存中是否已存在对应的MessageId,若存在则不再发送。
消费者角度
- 唯一ID + 消费记录表
- 消费者接收到消息后,从消息中提取出唯一ID(如生产者生成的全局唯一ID)。
- 在消费消息前,查询消费记录表,判断该唯一ID的消息是否已被消费。
- 若已消费,则直接返回,不再重复消费;若未消费,则进行正常的消息消费逻辑,并在消费成功后将该唯一ID记录到消费记录表中。
- 使用缓存
- 消费者接收到消息后,从消息中获取唯一标识。
- 先查询缓存(如Redis),判断该唯一标识的消息是否已被处理。
- 如果缓存中存在该标识,说明消息已被消费过,直接返回;否则进行消息处理,并在处理成功后将该唯一标识存入缓存中,设置合理的过期时间。