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

假设你负责腾讯微信红包系统的技术运营,该系统在春节等节点会面临百万级用户同时抢红包的高并发场景。请设计一个技术方案,确保系统在峰值时仍能保持低延迟、高吞吐,并具备故障恢复能力。请从架构设计、核心组件选型、数据一致性处理等方面展开说明。

Tencent技术运营难度:困难

答案

1) 【一句话结论】
核心采用“分层解耦+异步解耦+缓存加速+分布式保障+限流熔断”架构,通过滑动窗口限流控制流量、Redis缓存提升查询效率、分布式锁保障并发安全、Kafka异步处理请求,结合主从复制、持久化存储保障故障恢复,确保百万级高并发下的低延迟高吞吐与数据一致性。

2) 【原理/概念讲解】
老师:高并发抢红包的核心挑战是流量突发、并发安全、数据一致性。类比超市抢购,系统需像“智能收银台(限流)+分拣中心(消息队列)+库存管理(缓存+分布式锁)+库存同步(数据库)”运作。

  • 限流:用滑动窗口算法(每秒QPS阈值如1000次,动态调整窗口大小),避免突发流量压垮系统。
  • 缓存加速:Redis集群存红包信息(剩余数量、抢到状态),查询时直接从缓存取。为防缓存穿透(空值查询全量数据库),用布隆过滤器(误判率约1%)过滤无效请求,再用互斥锁(Redis SETNX)保证单次查询数据库。
  • 分布式锁:用Redis SETNX实现,设置过期时间(抢红包流程最长时间+缓冲,如3秒),若锁超时未释放,用户超时后可重试。
  • 异步解耦:Kafka持久化消息(确保不丢失),将“用户请求”与“扣减库存”解耦,消费者异步处理,避免同步阻塞。
  • 数据一致性:采用最终一致性——用户抢到后,先更新缓存(Redis),再异步写入数据库(MySQL),通过消息队列保证顺序。若数据库写入失败,缓存回滚到原值(如扣减失败则恢复剩余数量)。
  • 故障恢复:Redis主从复制+哨兵实现高可用;Kafka持久化+消费组保证消息不丢失;数据库主从读写分离保障读写性能。

3) 【对比与适用场景】

算法/组件定义特性使用场景注意点
滑动窗口限流统计当前窗口内请求数,超过阈值拒绝动态调整,抗突发能力强高频请求(如抢红包)需精确计算窗口边界,避免超卖
Redis分布式锁SETNX实现单机锁,设置过期时间单机锁,分布式需主从保障并发安全(如抢红包)过期时间≥最慢操作时间+缓冲,防死锁
Kafka消息队列持久化消息,支持消费组解耦、异步、高吞吐处理高并发请求需持久化存储,避免消息丢失
布隆过滤器基于位图的哈希集合空间高效,误判率低缓存穿透过滤无效请求误判率约1%,需结合互斥锁

4) 【示例】(伪代码):

# 用户抢红包流程(含重试、死信队列、缓存回滚)
def抢红包(user_id,红包id):
    # 1. 滑动窗口限流(QPS=1000)
    if not 检查限流(user_id):
        return "限流中"
    
    # 2. 缓存穿透处理(布隆过滤器+互斥锁)
    if not 布隆过滤器过滤(红包id):
        return "已抢完"
    lock_key = f"抢红包_互斥锁_{红包id}"
    if not redis.setnx(lock_key, "1", ex=1): # 1秒互斥锁
        return "抢夺失败(互斥锁占用)"
    
    # 3. 分布式锁(SETNX)
    lock_key = f"抢红包_分布式锁_{红包id}"
    if not redis.setnx(lock_key, "1", ex=3): # 3秒过期
        return "抢夺失败(锁被占用)"
    
    # 4. 扣减缓存数量
    剩余数量 = redis.decr(f"红包{红包id}_数量")
    if 剩余数量 < 0: # 超卖,回滚
        redis.incr(f"红包{红包id}_数量") # 回滚
        redis.delete(lock_key)
        return "超卖,重试"
    
    # 5. 异步写入数据库(Kafka)
    kafka_producer.send("抢红包日志", value={"user_id": user_id, "红包id": 红包id, "剩余数量": 剩余数量})
    
    # 6. 释放锁
    redis.delete(lock_key)
    redis.delete(lock_key) # 互斥锁
    
    return "抢到红包!"

(注:Kafka消费者处理消息时,若数据库写入失败,则将消息投递至死信队列,后续重试或记录日志。)

5) 【面试口播版答案】
面试官您好,针对微信红包系统百万级高并发场景,我的方案核心是构建“分层解耦+异步处理+缓存加速+分布式保障”的架构,确保低延迟和高吞吐。
首先,架构上采用微服务拆分(如红包生成、抢红包、统计模块独立部署),通过API网关统一入口实现水平扩展。然后,核心组件选型:限流用滑动窗口算法(每秒QPS阈值1000次,动态调整窗口大小),缓存用Redis集群(高可用+高并发),分布式锁用RedisSETNX(设置3秒过期时间,防止死锁),消息队列用Kafka(持久化+消费组)。数据一致性方面,采用最终一致性——用户抢到后,先更新缓存(Redis),再异步写入数据库(MySQL),通过消息队列保证顺序。若数据库写入失败,缓存回滚到原值(如扣减失败则恢复剩余数量)。故障恢复方面,Redis主从复制+哨兵实现高可用,Kafka持久化+消费组保证消息不丢失,数据库主从读写分离保障读写性能。这样在峰值时,限流控制流量,缓存加速查询,分布式锁保障并发安全,消息队列异步处理请求,整体保障低延迟和高吞吐,同时具备故障恢复能力。

6) 【追问清单】

  • 问题1:消息队列消费失败后如何处理?
    回答要点:若Kafka消费者处理失败,将消息投递至死信队列,后续重试或记录日志,避免数据丢失。
  • 问题2:分布式锁的过期时间怎么设置?
    回答要点:设置为抢红包流程最长时间(如2秒)+缓冲时间(如1秒),防止死锁。
  • 问题3:缓存穿透如何处理?
    回答要点:用布隆过滤器(误判率约1%)过滤无效请求,再用互斥锁(Redis SETNX)保证单次查询数据库。
  • 问题4:数据库写入失败时如何回滚?
    回答要点:缓存回滚到原值(如扣减失败则恢复剩余数量),通过消息队列保证最终一致性。
  • 问题5:如何测试性能?
    回答要点:用JMeter模拟并发请求,测试不同QPS下的延迟和吞吐,优化限流阈值和缓存策略。

7) 【常见坑/雷区】

  • 忽略限流,直接放行所有请求导致系统崩溃;
  • 缓存穿透未处理,导致全量数据库查询;
  • 分布式锁未设置过期时间,导致死锁;
  • 消息队列未做持久化,导致消息丢失;
  • 数据库写入失败未回滚,导致数据不一致。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1