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

设计一个支持百万级用户、低延迟消息推送的PC客户端消息系统,需要考虑网络传输、消息队列、缓存、消息去重等。请说明如何保证消息不丢失、不重复,以及如何处理网络波动时的重试机制。

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

答案

1) 【一句话结论】采用消息队列(如RocketMQ/Kafka)作为核心传输层,结合客户端本地缓存(内存+Redis)实现消息去重,网络波动时通过指数退避策略重试,确保百万级用户下消息不丢失、不重复且低延迟。

2) 【原理/概念讲解】
老师:咱们先讲核心组件的作用。消息队列是异步通信的“快递站”,客户端发消息给队列(寄件),服务端从队列取(取件),即使队列断网,寄件也不会丢失——这就是持久化存储的作用,保证消息不丢失。
类比:就像快递公司,寄件人把包裹寄到快递站,快递站即使断网,包裹也不会丢,等恢复后继续派送。
接下来是缓存,客户端发送消息后,先存到本地缓存(如Redis),标记为“未确认”,服务端处理前检查缓存,避免重复处理——这就是去重。
去重逻辑:用消息唯一ID(如UUID)或消息键(key),客户端发送前先查缓存,有则跳过,无则发送。
网络波动重试:客户端发送失败后,按指数退避策略重试(如第一次1秒,第二次2秒,第三次4秒...),避免频繁请求压垮服务器,同时保证重试成功率。

3) 【对比与适用场景】

模块定义特性使用场景注意点
消息队列(如RocketMQ)分布式消息中间件,支持持久化、顺序、事务高吞吐、持久化、支持重试、事务核心传输,保证消息不丢失,处理网络波动需集群部署,消息延迟毫秒级
本地缓存(如Redis)客户端本地存储未确认消息低延迟、内存访问快存储临时未确认消息,去重需内存管理,避免内存泄漏

4) 【示例】
伪代码(客户端发送消息):

def send_message(message_id, content):
    # 1. 本地缓存去重(Redis)
    if redis.exists(f"msg:{message_id}"):
        return "duplicate"
    # 2. 发送消息到队列(RocketMQ)
    mq_producer.send(message_id, content)
    # 3. 存储到本地缓存(标记为未确认)
    redis.set(f"msg:{message_id}", "pending")
    return "sent"

伪代码(服务端处理消息):

def process_message(message_id, content):
    # 1. 检查本地缓存(标记为已处理)
    if redis.exists(f"msg:{message_id}"):
        redis.set(f"msg:{message_id}", "processed")
        process_content(content)  # 处理消息(如更新UI)
        return "processed"
    else:
        # 从队列取消息
        msg = mq_consumer.consume(message_id)
        process_content(msg)
        redis.set(f"msg:{message_id}", "processed")
        return "processed"

5) 【面试口播版答案】
面试官您好,针对百万级用户低延迟消息推送系统,核心思路是用消息队列(如RocketMQ)做可靠传输,结合客户端本地缓存去重,网络波动时用指数退避重试。
具体来说,消息从客户端发送到队列后,服务端通过消费队列处理,客户端本地缓存存储未确认消息,避免重复处理。去重通过消息唯一ID(或消息键)在Redis中检查,确保同一消息只处理一次。网络波动时,客户端根据指数退避策略重试(如第一次1秒,第二次2秒...),避免频繁请求压垮服务器。这样能保证消息不丢失、不重复,同时低延迟。

6) 【追问清单】

  • 问:消息去重时,客户端生成的ID如何避免跨客户端冲突?
    回答要点:使用全局唯一ID(如UUIDv4),或结合时间戳+随机数,确保ID唯一性。
  • 问:重试机制中,指数退避的参数(初始时间、最大次数)如何设置?
    回答要点:初始重试时间1秒,最大重试次数5次,超过后放弃,避免无限重试。
  • 问:消息持久化如何保证?比如队列是否支持事务?
    回答要点:消息队列支持磁盘持久化,确保网络中断后消息不丢失;事务消息支持事务提交,保证最终一致性。
  • 问:如何处理消息顺序性?比如聊天消息需要按发送顺序显示?
    回答要点:消息队列支持顺序消息(如RocketMQ的顺序消息),通过消息键关联,保证同一key的消息顺序消费。
  • 问:跨机房部署时,消息队列如何保证一致性?
    回答要点:支持多机房部署(如RocketMQ分布式集群),通过数据同步,确保跨机房消息可靠传输,延迟控制在毫秒级。

7) 【常见坑/雷区】

  • 坑1:未持久化消息队列导致消息丢失。反问:如果消息队列单点故障,如何保证消息不丢失?
  • 坑2:去重逻辑错误(仅用时间戳),时间同步问题导致重复处理。反问:客户端时间不同步时,时间戳去重是否有效?
  • 坑3:重试策略不当(线性重试),导致服务器压力过大。反问:网络波动频繁时,指数退避是否合理?
  • 坑4:缓存击穿问题,大量客户端同时发送消息导致缓存穿透。反问:如何避免缓存击穿?
  • 坑5:消息顺序混乱,未正确处理顺序消息。反问:如何保证聊天消息按发送顺序显示?
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1