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

描述你参与过的移动客户端大促活动(如微信红包或双11),你负责的模块(如消息推送或支付接口)遇到的高并发问题,以及采取的解决方案。请说明问题背景、问题表现、解决方案及效果评估。

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

答案

1) 【一句话结论】

在双11红包大促中,我负责的消息推送模块通过引入Kafka消息队列异步解耦、动态令牌桶限流控制请求速率、以及基于失败率的熔断机制,成功应对百万级并发。压力测试显示,模拟100万并发请求时,平均响应时间从500ms降至50ms,失败率从5%降至0.1%,活动期间用户红包通知延迟低于1秒,用户满意度提升显著。

2) 【原理/概念讲解】

高并发场景下,用户同时点击领取红包时,消息推送接口瞬间承受海量请求(如百万级),导致接口响应超时甚至服务崩溃。为解决此问题,需理解以下核心机制:

  • 消息队列(异步处理):将推送任务异步写入队列(如Kafka),消费者按需处理,避免接口直接承受高并发。类比:快递中转站——用户下单后,订单先到中转站分拣,不会让下单瞬间就派送所有快递,实现请求与响应解耦。
  • 限流机制(令牌桶算法):通过令牌桶控制请求进入速率,像交通信号灯,限制每秒请求数(如每秒1000个令牌,每个请求消耗1个令牌),防止流量超过系统处理能力,保护后端服务。令牌桶允许突发流量(短时间内请求超过限流值,后续会补发令牌),适合突发大促场景。
  • 熔断机制:当服务失败率超过阈值(如50%),暂时拒绝请求,避免雪崩效应(如推送SDK调用失败时,熔断后不再调用,减少连锁故障,保障系统稳定性)。熔断分为CLOSED(正常)、OPEN(熔断)、HALF_OPEN(恢复中)状态,逐步恢复调用。

3) 【对比与适用场景】

方案定义特性使用场景注意点
消息队列(异步处理)将请求异步写入队列,消费者异步处理解耦、削峰、可水平扩展高并发推送、通知等场景(如红包、订单确认)需考虑消息丢失(设置重试机制)、延迟(调整消费者数量和批处理大小),避免队列积压导致延迟过高
限流(令牌桶)控制请求进入速率限制流量,保护系统防止流量过大导致系统崩溃(如秒杀、大促)需动态调整阈值(根据系统负载变化),避免误判(突发流量时允许少量超额),防止限流后用户请求被拒绝
熔断服务失败率超阈值时暂时拒绝请求防雪崩效应依赖服务不稳定时(如第三方推送SDK故障)需合理设置阈值(如失败率50%),避免误触发(失败率波动时逐步调整),恢复策略需平滑(按比例增加请求量)

4) 【示例】

伪代码(消息推送异步流程):

# 用户点击领取红包,将推送任务写入Kafka队列
def handle_receive_redpack(user_id, redpack_id):
    # 限流:检查令牌桶,不足则拒绝或排队
    if not token_bucket.check():
        return "请求过多,请稍后重试"
    # 将推送任务写入Kafka(高吞吐,支持百万级消息)
    kafka_producer.send("push_task", value={"user_id": user_id, "redpack_id": redpack_id})
    return "领取成功,通知中"

# 推送服务(消费者)消费队列消息,调用推送SDK
def consume_push_task():
    while True:
        msg = kafka_consumer.poll(timeout_ms=100)
        for record in msg:
            data = record.value
            # 生成推送内容(如微信消息)
            push_content = f"您领取了{data['redpack_id']}红包!"
            # 调用推送SDK(如微信小程序推送)
            wechat_push.send(data['user_id'], push_content)

限流逻辑(令牌桶,动态调整):

class TokenBucket:
    def __init__(self, capacity, refill_rate, monitor_interval=1):
        self.capacity = capacity  # 令牌桶容量
        self.refill_rate = refill_rate  # 每秒补充的令牌数(如1000个/秒)
        self.tokens = capacity
        self.last_refill = time.time()
        self.monitor_interval = monitor_interval  # 监控周期(秒)
    
    def check(self):
        now = time.time()
        # 动态调整:根据系统负载(如CPU使用率)调整令牌补充速率
        if now - self.last_refill >= self.monitor_interval:
            load = get_system_load()  # 获取系统负载(如CPU > 70%时降低补充速率)
            if load > 0.7:  # 负载过高时,补充速率减半
                self.refill_rate = self.refill_rate * 0.5
            else:
                self.refill_rate = self.refill_rate  # 正常补充
            self.last_refill = now
        self.tokens = min(self.capacity, self.tokens + (now - self.last_refill) * self.refill_rate)
        return self.tokens > 0

熔断逻辑(基于失败率,动态恢复):

class CircuitBreaker:
    def __init__(self, threshold=0.5, recovery_rate=0.1, recovery_step=0.1):
        self.threshold = threshold  # 失败率阈值(如50%)
        self.state = "CLOSED"  # 状态:CLOSED、OPEN、HALF_OPEN
        self.success_count = 0
        self.failure_count = 0
        self.recovery_rate = recovery_rate  # 恢复速率(如每秒10%的请求尝试)
        self.recovery_step = recovery_step  # 恢复步长(如每分钟增加10%的请求量)
    
    def request(self):
        if self.state == "OPEN":
            # 熔断状态下,允许少量请求尝试
            if random.random() < self.recovery_rate:  # 每秒10%的请求尝试
                return self._execute()
        elif self.state == "HALF_OPEN":
            # 恢复中,允许请求,并统计结果
            return self._execute()
        else:
            return self._execute()
    
    def _execute(self):
        try:
            # 调用推送SDK(模拟)
            wechat_push.send(...)
            self.success_count += 1
            return True
        except Exception as e:
            self.failure_count += 1
            return False
    
    def update_state(self):
        total = self.success_count + self.failure_count
        if total == 0:
            return
        failure_rate = self.failure_count / total
        if failure_rate > self.threshold and self.state == "CLOSED":
            self.state = "OPEN"
        elif failure_rate < self.threshold and self.state == "HALF_OPEN":
            # 逐步恢复,按步长增加请求量
            self.recovery_rate += self.recovery_step
            if self.recovery_rate > 1:
                self.recovery_rate = 1
            self.state = "CLOSED"

5) 【面试口播版答案】

(约90秒)
“我参与过双11红包大促,负责的消息推送模块在大促时遇到百万级并发。当时问题表现为用户点击领取后,红包通知延迟超过1秒甚至不推送,导致用户流失。解决方案是引入Kafka消息队列异步处理推送任务,配合动态令牌桶限流控制请求速率,同时设置基于失败率的熔断机制。具体来说,通过压力测试,模拟100万并发请求时,平均响应时间从500ms降至50ms,失败率从5%降至0.1%。活动期间,用户红包通知延迟低于1秒,用户满意度提升显著,未出现服务崩溃。”

6) 【追问清单】

  • 问题1:压力测试的具体数据?比如模拟100万并发时的响应时间、失败率?
    • 回答要点:压力测试中,模拟100万并发请求,平均响应时间从500ms降至50ms,失败率从5%降至0.1%。
  • 问题2:消息队列的延迟如何控制在1秒内?比如消费者数量和批处理大小?
    • 回答要点:通过调整Kafka消费者数量(如增加至10个消费者),设置批处理大小为100条/次,并优先处理高优先级任务(如红包通知),确保延迟在1秒内。
  • 问题3:限流阈值是如何动态调整的?比如根据系统负载?
    • 回答要点:根据系统负载动态调整,比如通过监控CPU、内存使用率,当负载超过70%时,降低限流阈值(如从每秒1000个令牌降至800个),反之则提高。
  • 问题4:熔断的恢复策略?比如每秒允许多少请求尝试?
    • 回答要点:熔断后,每秒允许10%的请求尝试调用推送SDK,并监控失败率,当失败率低于阈值时,逐步恢复调用(如每分钟增加10%的请求量)。

7) 【常见坑/雷区】

  • 坑1:效果评估缺乏具体数据支撑(如压力测试数据、用户反馈),显得方案不落地。需补充压力测试环境(如服务器配置、工具)和具体指标(响应时间、失败率)。
  • 坑2:技术选型依据不明确(如消息队列选型Kafka的理由)。需说明Kafka的高吞吐、低延迟特性,以及根据业务对延迟的要求(如红包通知需低延迟)选择。
  • 坑3:限流阈值动态调整策略不具体。需解释如何通过监控指标(如系统负载、队列积压)调整阈值,避免误判突发流量。
  • 坑4:熔断机制设置不当(如阈值过高或过低)。需说明阈值设置依据(如失败率50%),以及恢复策略的平滑性(按比例增加请求量)。
  • 坑5:未考虑容灾(如消息队列积压过多,没设置告警或自动扩容)。需说明队列积压告警机制(如超过阈值时触发扩容或通知运维)。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1