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

设计一个支持百万级用户、毫秒级响应的实时消息推送系统(类似微信的聊天消息),请从消息存储、消息队列、消息路由、消费端处理、容错与监控等方面进行系统设计,并说明如何保证消息不丢失、不重复。

Tencent软件开发-移动客户端开发方向难度:困难

答案

1) 【一句话结论】
核心设计是构建以Kafka为核心的分布式消息系统,结合Redis缓存和MySQL持久化存储,通过用户ID/会话ID路由实现毫秒级推送,并采用生产者确认、消费者偏移提交、重试与死信队列、幂等处理等机制保障消息不丢失、不重复。

2) 【原理/概念讲解】
老师:我们逐个拆解核心组件的原理,确保每个点都落地。

  • 消息存储:分为缓存(Redis,用于热数据毫秒级读取,类比快递柜,快速取件)和持久化(MySQL,存储消息元数据+内容,保证数据持久化,类比快递仓库,确保不丢失)。
  • 消息队列:选择Kafka(高吞吐、持久化、低延迟),生产者将消息发送到分区,消费者从分区消费,支持多消费者并行处理(类比分拣中心,多个分拣员同时处理包裹,提升效率)。
  • 消息路由:根据消息接收者(用户ID)或会话ID,将消息路由到对应消费端(客户端长连接队列),确保精准投递(类比快递分拣,根据收件人地址分拣包裹)。
  • 消费端处理:客户端通过WebSocket/TCP长连接订阅消息队列的特定主题/分区,实时接收消息并更新UI(类比快递员收到包裹后立即送达用户)。
  • 容错与监控:消息重试(失败后重发)、死信队列(多次失败的消息进入)、幂等处理(通过消息ID或状态机确保单次处理)、监控(跟踪延迟、吞吐量、错误率,类比快递物流的监控,确保流程顺畅)。

3) 【对比与适用场景】

组件定义特性使用场景注意点
消息队列(Kafka)分布式消息系统,基于发布-订阅模式高吞吐、持久化、低延迟、多消费者实时消息推送、日志收集需合理配置分区数(如按用户数或会话ID分区),消费者组管理
缓存(Redis)内存数据库,支持多种数据结构毫秒级读写、高并发、内存限制热数据缓存、会话存储需持久化(RDB/AOF),避免数据丢失
持久化存储(MySQL)关系型数据库事务支持、持久化、查询消息元数据(ID、时间、状态)写性能需优化(分库分表),避免单点瓶颈

4) 【示例】

  • 生产者发送消息(伪代码):
    # 假设使用Kafka生产者
    producer.send(topic='chat_messages', key=user_id, value=message)  # key用于路由
    producer.flush()  # 确保消息发送到Kafka
    
  • 消费者消费消息(伪代码):
    # 消费者订阅主题,按key分区
    consumer.subscribe(topics=['chat_messages'], key_deserializer=lambda k: str(k).encode('utf-8'))
    while True:
        msg = consumer.poll(timeout=1.0)
        if msg:
            process_message(msg.value)  # 处理消息(更新Redis缓存、推送客户端)
    
  • 消息持久化存储(SQL示例):
    INSERT INTO chat_messages (user_id, session_id, content, send_time, status)
    VALUES (user_id, session_id, message, NOW(), 'sent')
    
  • 客户端接收(JS示例):
    // WebSocket连接
    socket.onmessage = function(e) {
        const msg = JSON.parse(e.data);
        // 更新UI,显示消息
    }
    

5) 【面试口播版答案】
面试官您好,针对百万级用户、毫秒级响应的实时消息推送系统,我的核心设计是构建以Kafka为核心的分布式消息架构,结合Redis缓存和MySQL持久化存储,通过用户ID/会话ID路由实现快速推送,并采用生产者确认、消费者偏移提交、重试与死信队列、幂等处理等机制保障消息不丢失、不重复。具体来说,消息由生产者发送到Kafka,通过分区和消费者组实现高并发消费;Redis缓存热数据提升读取速度;MySQL存储消息元数据保证持久化。消息路由根据接收者ID将消息推送到客户端长连接队列,客户端实时接收。容错方面,失败消息会重试,多次失败进入死信队列;通过消息ID或状态机实现幂等,避免重复消费。监控方面,跟踪消息延迟、吞吐量、错误率,确保系统稳定。

6) 【追问清单】

  • 问:如何保证消息不丢失?
    回答要点:生产者发送确认(acks=all),确保消息写入Kafka日志;消费者偏移提交(commit offset),确保消费进度持久化;Kafka日志持久化(日志保留策略,如保留时间或大小)。
  • 问:消息重复消费怎么处理?
    回答要点:通过消息ID作为唯一标识(确保每条消息唯一),或通过状态机(如消息状态表,标记已处理状态)实现幂等,确保消息只处理一次。
  • 问:系统如何扩展?
    回答要点:消息队列分区扩展(如按用户数增加分区,每个用户一个分区);缓存分片(按用户ID分片,提升缓存命中率);数据库分库分表(按用户ID分库,分散写压力)。
  • 问:如何保证毫秒级响应?
    回答要点:假设网络延迟低(如内部网络),客户端长连接减少连接建立时间;Redis缓存热数据,减少数据库查询延迟;Kafka分区与消费者组优化,避免消费者积压。
  • 问:监控指标有哪些?
    回答要点:消息延迟(生产者到消费者时间)、吞吐量(每秒消息数)、错误率(失败消息占比)、重试次数(失败后重发次数)。

7) 【常见坑/雷区】

  • 消息丢失:未配置生产者确认(acks=all)或消费者偏移提交,导致消息未持久化或消费进度丢失。
  • 重复消费:未做幂等处理(如无消息ID或状态机),导致消息重复处理。
  • 路由错误:消息未按用户ID/会话ID正确分区,导致消息投递到错误客户端。
  • 缓存雪崩:缓存失效时大量请求,未做缓存预热或限流,影响性能。
  • 消费者积压:消息队列分区不足,导致消费者处理不过来,消息堆积。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1