最近面试美团AI面问了这么一个问题 我收集了资料并进行了复盘

面试官:请你谈谈如何设计一个秒杀系统

我: 我的思路是这样的:

在开始设计之前、我认为最重要的是需求对齐。我们需要明确以下几个关键问题:

  • 秒杀什么商品? 不同的商品可能对系统的压力不同、例如热门商品需要更高的并发处理能力。

  • 秒杀时间? 秒杀开始和结束的时间点、以及持续时间、会影响流量的峰值和系统的负载。

  • 秒杀数量? 秒杀商品的数量直接决定了库存管理的复杂度和数据一致性的要求。

  • 是否有购买限制? 例如每个用户限购数量、这会影响风控策略的设计。

  • 是否允许小概率超卖/少卖? 这会影响我们对数据一致性的选择、是选择强一致性还是最终一致性。

了解这些信息可以帮助我们更好地评估系统的复杂度和风险、并选择合适的技术方案。例如:

  • 请求量预估: 根据商品的热度和用户数量、我们可以预估秒杀期间的请求量。如果请求量在5k以内、可能单机MySQL就能抗住、如果达到10w以上、就需要考虑Redis集群和更复杂的架构。

  • 数据一致性选择: 如果不允许超卖、我们需要使用强一致性的方案、例如MySQL的事务

  • 如果允许小概率超卖、可以使用最终一致性的方案、例如Redis预扣库存+异步更新MySQL。

  • 风控策略设计: 根据是否有购买限制、我们可以设计相应的风控策略、例如限制IP地址、验证码等。

在明确了需求之后、我会进行难点分析。我认为秒杀系统主要面临以下几个难点:

  • 高并发: 秒杀活动会瞬间产生巨大的流量、对系统的并发处理能力提出很高的要求。

  • 高一致性: 需要保证库存的准确性、防止超卖或少卖。

  • 用户体验: 需要保证用户能够流畅地参与秒杀、避免出现卡顿或错误。

  • 黄牛: 需要防止黄牛党利用脚本抢购商品、保证活动的公平性。

首先、我会从整体架构入手。秒杀系统需要一个清晰的分层结构、一般可以分为:

  • 接入层: 负责接收用户的请求、进行初步的校验和限流。

  • 服务层: 处理核心的业务逻辑、例如库存扣减、订单生成等。

  • 数据层: 负责数据的存储和访问、例如MySQL、Redis等。

每一层都可以独立扩展和优化、降低系统的耦合度。

然后我会考虑关键技术点。我认为以下几个技术点在秒杀系统中至关重要:

  • 库存管理: 这是秒杀系统的核心。为了提高性能、我会使用Redis预扣库存。也就是说、秒杀开始前,、商品的库存加载到Redis中、用户请求到达时、先在Redis中扣减库存。如果Redis扣减成功、再异步地更新MySQL数据库。这样做可以大大减轻数据库的压力。

    • 面试官可能会问:如果Redis挂了怎么办

    • 我:Redis的可靠性确实不如MySQL。为了应对这种情况、我会采取以下措施:

      • 持久化: 开启Redis的持久化功能、例如RDB或AOF,防止数据丢失。

      • 主从复制: 使用Redis主从复制、提高系统的可用性。

      • 最终一致性: 即使Redis出现故障、导致少量超卖、也可以通过后续的补偿机制来解决

  • 请求处理: 秒杀系统需要处理大量的并发请求。为了防止系统崩溃、我会采取以下措施:

    • 限流: 使用Nginx或网关进行限流、防止恶意请求和过多的请求涌入系统。

    • 削峰: 使用消息队列(例如Kafka)进行异步处理、将请求放入队列中、由消费者慢慢处理、避免瞬间的流量冲击。

  • 安全: 秒杀系统容易受到黄牛党的攻击。为了保证公平性、我会采取以下措施:

    • 验证码: 增加验证码、防止机器人刷单。

    • 限购: 限制单个用户的购买数量。

    • 风控系统: 使用风控系统识别恶意用户、例如通过IP地址、设备信息等。

接下来我会详细描述秒杀流程:

  1. 用户访问秒杀页面、静态资源从CDN加载、动态数据从服务器获取。

  2. 用户点击秒杀按钮、前端进行简单校验(例如按钮状态、用户登录状态)。

  3. 请求到达后端、接入层进行限流和风控。

  4. 服务层使用Lua脚本在Redis中预扣库存。

  5. 如果预扣成功、将请求放入消息队列。

  6. 消息队列消费者从队列中获取请求、减MySQL库存、创建订单、更新Redis秒杀信息状态。

  7. 用户支付、完成订单。

  8. 如果用户超时未支付、定时任务扫描未支付订单、释放Redis预扣库存。

最后我谈谈难点与解决方案:

  • 高并发: 通过限流、削峰、缓存等手段缓解压力。

  • 超卖: 使用Redis预扣库存和MySQL最终一致性保证。

  • 少卖: 使用定时任务扫描未支付订单、释放库存。

  • 黄牛: 通过风控系统、验证码、限购等手段打击黄牛。

总的来说设计秒杀系统需要综合考虑性能、一致性、安全性和用户体验等多个方面。

通过合理的技术选型和架构设计、可以构建一个高性能、高可用的秒杀系统。

我认为还有以下几个可以优化的点:

  • 页面静态化: 将秒杀页面尽可能地静态化、减少服务器的动态请求。

  • CDN加速: 使用CDN加速静态资源的访问、提高用户体验。

  • 预热: 在秒杀开始前、预热Redis缓存、避免冷启动。

  • 监控: 实时监控系统性能、及时发现和解决问题。

  • 弹性伸缩: 根据流量情况动态调整服务器资源。

这些优化措施可以进一步提高秒杀系统的性能和可用性。

更多推荐