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

在腾讯的微信红包系统中,前端如何处理高并发下的请求(如抢红包),避免请求超时或重复提交?请设计一个前端方案。

Tencent软件开发-前端开发方向难度:中等

答案

1) 【一句话结论】
针对微信红包高并发抢发场景,前端通过“请求去重(本地存储唯一标识)、频率控制(防抖)、服务端幂等性配合”三重机制,结合网络异常的指数退避重试,确保请求不重复提交且系统稳定。

2) 【原理/概念讲解】
首先解释“请求去重”的核心:为每个抢红包请求生成唯一标识,前端通过本地存储(如sessionStorage)记录已提交标识,避免同一标识重复发送。类比“快递单号”,每个包裹有唯一编号,系统通过单号判断是否已处理,避免重复投递。接着说明“频率控制”:用户快速点击可能导致多次请求,需用防抖(Debounce)函数控制,连续触发事件后延迟执行(如用户快速点击抢红包按钮,只发送最后一次请求)。再解释“服务端配合”:前端去重是基础,但服务端需实现幂等性(重复请求不产生重复结果),比如通过请求头中的唯一标识判断是否已处理,或用数据库事务保证结果唯一(如将标识存入数据库,若已存在则返回“已抢”状态)。最后补充“网络异常处理”:当请求超时或失败时,采用指数退避策略,随机等待1-30秒后重试,避免请求雪崩。

3) 【对比与适用场景】
对比唯一标识生成策略(时间戳+随机数 vs UUID+时间戳):

策略名称定义特性使用场景注意点
时间戳+随机数请求时生成时间戳+随机数依赖时间戳,易被篡改低并发或对唯一性要求不高需确保时间戳准确性,避免重复
UUID+时间戳请求时生成UUID+时间戳UUID全局唯一,时间戳辅助高并发场景,保证唯一性UUID生成稍耗时,但前端效率高

对比存储方案(localStorage vs sessionStorage):

存储方案定义特性适用场景注意点
localStorage全局存储,多标签页共享跨标签页共享,持久化单标签页或需跨标签页共享多标签页时标识冲突
sessionStorage会话级存储,标签页独立每个标签页独立,会话结束清除多标签页抢红包会话内隔离,避免冲突

4) 【示例】
抢红包按钮的点击事件处理(含防抖、sessionStorage、请求头标识、服务端幂等性、指数退避):

// 生成唯一请求标识(UUID+时间戳,更安全)
function generateRequestId() {
  return 'uuid' + Date.now().toString() + Math.random().toString(36).substr(2);
}

// 防抖函数,控制点击频率
function debounceClick(func, delay) {
  let timer;
  return function() {
    clearTimeout(timer);
    timer = setTimeout(() => {
      func();
    }, delay);
  };
}

// 抢红包按钮事件处理
const grabBtn = document.getElementById('grab-btn');
grabBtn.addEventListener('click', debounceClick(() => {
  const requestId = generateRequestId();
  // 检查sessionStorage是否已有该请求标识(多标签页隔离)
  if (sessionStorage.getItem('grab-request-id')) {
    console.log('已提交过请求,忽略');
    return;
  }
  // 存储标识,避免重复
  sessionStorage.setItem('grab-request-id', requestId);
  
  // 发送请求,携带唯一标识
  fetch('/api/grab', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Request-Id': requestId
    },
    body: JSON.stringify({ userId, redpackId })
  })
  .then(res => {
    if (res.ok) {
      console.log('抢到红包');
      sessionStorage.removeItem('grab-request-id'); // 成功后清除标识
    } else {
      console.log('抢失败');
    }
  })
  .catch(err => {
    console.error('请求错误');
    // 网络异常后,指数退避重试
    retryRequest(requestId);
  });
}, 300); // 300ms防抖,避免快速点击

// 指数退避重试函数
function retryRequest(requestId) {
  const randomBackoff = Math.min(1000 * Math.pow(2, Math.floor(Math.random() * 5)), 30000); // 1-30秒随机退避
  setTimeout(() => {
    // 重新发送请求,检查sessionStorage标识(避免重复)
    if (!sessionStorage.getItem('grab-request-id')) {
      fetch('/api/grab', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-Request-Id': requestId
        },
        body: JSON.stringify({ userId, redpackId })
      })
      .then(res => res.ok ? console.log('重试成功') : console.log('重试失败'))
      .catch(err => console.error('重试失败'));
    }
  }, randomBackoff);
}

// 服务端幂等性示例(数据库操作伪代码)
// 假设数据库表redpacks,字段request_id(唯一索引)
// 事务处理:
// BEGIN TRANSACTION;
// INSERT INTO redpacks (request_id, user_id, redpack_id) VALUES (?, ?, ?);
// ON DUPLICATE KEY UPDATE status = 'grabbed'; -- MySQL唯一索引冲突处理
// COMMIT;

5) 【面试口播版答案】
“面试官您好,针对微信红包抢发的高并发场景,前端方案的核心是通过‘请求去重(本地存储唯一标识)、频率控制(防抖)、服务端幂等性配合’三重机制,结合网络异常的指数退避重试,确保请求不重复提交且系统稳定。具体来说,前端为每个抢红包请求生成唯一标识(如UUID+时间戳),存储在sessionStorage中,避免同一标识在多标签页重复发送;同时用300ms防抖函数控制用户快速点击,防止多次请求;请求头携带该标识,服务端通过标识判断是否已处理,实现幂等性(如数据库唯一索引或事务保证结果唯一)。此外,网络异常时采用指数退避策略,超时后随机等待1-30秒再重试,避免请求雪崩;多标签页时,每个标签页使用独立的sessionStorage标识,避免跨标签页冲突;若用户清除缓存,标识丢失后重新生成,确保去重逻辑仍有效。这样前端既解决了重复提交问题,又通过后端配合和异常处理保证了高并发下的稳定性。”

6) 【追问清单】

  • 问题1:服务端如何实现幂等性?
    回答要点:服务端通过请求头中的唯一标识查询数据库,若已存在则返回已处理状态(如“已抢”),或使用数据库事务(如乐观锁/悲观锁)保证结果唯一。
  • 问题2:多个标签页同时抢红包时,如何避免标识冲突?
    回答要点:每个标签页使用sessionStorage存储请求标识(如sessionStorage.setItem('grab-id', tabId + requestId)),不同标签页的sessionStorage独立,标识不冲突。
  • 问题3:指数退避的具体实现逻辑?
    回答要点:超时后,随机等待1秒、2秒、4秒等(指数级增长),避免大量请求集中重试,减少服务器压力。

7) 【常见坑/雷区】

  • 坑1:忽略服务端幂等性,仅依赖前端去重。
    雷区:服务端未处理幂等性,前端去重失效,导致重复提交,需服务端配合(如数据库唯一索引)。
  • 坑2:使用localStorage作为多标签页去重存储,导致标识冲突。
    雷区:localStorage全局共享,不同标签页标识相同,需使用sessionStorage或tab ID区分。
  • 坑3:网络异常处理不当,未设置指数退避。
    雷区:直接重试可能导致请求雪崩,需指数退避避免服务器压力过大。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1