51mee - AI智能招聘平台Logo
模拟面试题目大全招聘中心会员专区

设计一个课程通知系统,用户报名课程后,需要发送短信或邮件通知,请说明如何使用消息队列保证消息可靠传递,并处理延迟消息(如用户在报名后1小时收到通知)。

好未来后端 - Java难度:中等

答案

1) 【一句话结论】采用消息队列(如RabbitMQ/Kafka)实现用户报名与通知的异步解耦,通过持久化存储、消费端确认机制保证消息可靠传递,结合延迟队列处理1小时后的通知,确保消息不丢失且延迟准确。

2) 【原理/概念讲解】老师口吻解释:消息队列的核心是解耦用户报名服务(生产者)与通知服务(消费者),实现异步处理。可靠传递需满足两点:一是消息持久化(存储至磁盘,避免内存丢失),二是消费端需发送ACK确认,若消费失败则消息保留重试;延迟消息处理则通过消息头设置延迟时间(如1小时),队列按时间排序消费。简单类比:消息队列像快递中转站,生产者把包裹(消息)放进去,消费者(通知服务)按顺序取。若消费者没取(消费失败),包裹留到第二天(重试),若一直取不到,送退件中心(死信队列)。延迟包裹则放在特定货架(延迟队列),过时间后取出。

3) 【对比与适用场景】

维度可靠传递(核心机制)延迟消息处理(关键机制)
定义保证消息不丢失,处理失败后重试消息延迟一定时间后消费
核心技术持久化队列 + 消费端ACK确认延迟交换机(RabbitMQ)或延迟主题(Kafka) + TTL
处理逻辑消费失败,消息保留,重试或死信消息头设置延迟时间,队列按时间排序,过时间后消费
适用场景用户报名后需立即/稍后发送通知,且不能丢失用户报名后1小时发送通知(如课程开课前提醒)

4) 【示例】(伪代码,以RabbitMQ为例,含幂等性处理)
生产者(用户报名服务):

// 发送消息到队列,设置延迟1小时(3600秒)
channel.basicPublish("registration-queue", "registration", 
    MessageProperties.PERSISTENT_TEXT_PLAIN,
    ("user_id:" + user.getId() + ",course_id:" + course.getId() + ",type:" + type).getBytes());
// 检查幂等性:数据库记录用户是否已发送通知
if (isNotificationSent(userId, courseId, type)) {
    return; // 跳过重复处理
}

消费者(通知服务):

public void processMessage(Message message) {
    String body = new String(message.getBody(), StandardCharsets.UTF_8);
    String[] parts = body.split(",");
    String userId = parts[0].split(":")[1];
    String courseId = parts[1].split(":")[1];
    String type = parts[2].split(":")[1];
    
    // 检查幂等性:查询数据库,用户是否已收到通知
    if (isNotificationSent(userId, courseId, type)) {
        return; // 跳过,避免重复
    }
    
    // 处理消息
    if (type.equals("SMS")) {
        sendSMS(userId, courseId);
    } else if (type.equals("EMAIL")) {
        sendEmail(userId, courseId);
    }
    
    // 确认消息已处理
    channel.basicAck(message.getDeliveryTag(), false);
}

5) 【面试口播版答案】
面试官您好,课程通知系统需要用户报名后异步发送短信或邮件,为保障消息可靠传递并处理延迟通知,我会采用消息队列(如RabbitMQ或Kafka)实现解耦。具体来说,用户报名服务作为生产者,将包含用户、课程和通知类型的消息发送到队列,并设置延迟时间(比如1小时)。消息队列通过持久化存储和消费端确认机制保证消息不丢失,如果消费者处理失败,消息会重试或进入死信队列。对于延迟消息,队列会根据消息头中的延迟时间排序,过时间后由消费者处理,确保用户在报名后1小时收到通知。同时,通过数据库记录或分布式锁实现消息幂等性,避免重复发送通知,提升用户体验。这样既解耦了报名和通知流程,又保证了消息可靠性和延迟处理的准确性。

6) 【追问清单】

  • 问:消息队列选RabbitMQ还是Kafka?答:RabbitMQ适合简单队列和延迟交换机,Kafka适合高吞吐和持久化,这里若需高并发和持久化,选Kafka,延迟处理用延迟主题。
  • 问:如何处理消息幂等性?答:处理消息前检查用户是否已收到通知(如数据库记录),避免重复发送。
  • 问:延迟消息队列积压怎么办?答:设置合理队列容量和消费者数量,或用死信队列处理积压,避免影响主流程。
  • 问:通知服务宕机后消息丢失?答:消息队列持久化,消费者重试机制,或死信队列后续人工处理。

7) 【常见坑/雷区】

  • 未消息持久化:导致用户报名后消息丢失,通知不发送。
  • 延迟消息实现错误:直接应用层延迟,导致队列积压或消息延迟。
  • 忽略消息幂等性:重复发送通知,影响用户体验。
  • 消费者失败后无重试/死信队列:消息丢失,用户收不到通知。
  • 消息队列选择不当:同步方式阻塞用户报名,影响系统性能。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1