UP | HOME

如何设计一个秒杀系统

Table of Contents

本文章是极客时间 《如何设计一个秒杀系统》 的学习笔记

1 开篇词 秒杀系统都有哪些关键点

秒杀系统主要解决两个问题:并发度和并发写。

并发读的优化理念:尽量减少用户到服务端来“读”数据,或者让他们读更少的数据。

并发写的优化理念:在数据库层面独立出来一个库,做特殊处理。

实践原则:

  • 用户请求的数据尽量少: 动静分离。
  • 请求数尽量少: 根据 UID、IP 限流。
  • 路径尽量短,依赖尽量少。
  • 不要有单点。

优化路径:

  1. 前端秒杀页面:
    • 动静分离
    • 限流(比如限制页面刷新或者点击)
  2. 中间代理:
    • 限流,nginx 限制请求并发
    • 分流,对请求 hash
    • 负载均衡和横向扩容
  3. 后端服务
    • 限流防刷
    • 横向扩容
    • 业务分离,不影响正常业务
    • 异步处理,如消息队列
  4. 数据层:
    • 分库分表
    • 读写分离
    • 缓存读写,异步落盘
    • 业务分离

架构特性:

  • 高性能:数据动静分离、热点发现与隔离、请求的削峰和分层过滤、服务端极致优化
  • 一致性:减库存
  • 高可用:Plan B

2 01 设计秒杀系统时应该注意的 5 个架构原则

架构原则:4要 1 不要:

  • 数据要尽量少,减少 CPU 消耗。
  • 请求数要尽量少。减少加载时间。实践:合并 css 和 js 文件。
  • 路径要尽量短,减少节点消耗。
  • 依赖要尽量少。
  • 不要有单点。避免服务状态和机器绑定,即服务无状态化。

3 02 如何才能做好动静分离

如何缓存静态数据:

  • 把静态数据缓存到离用户最近的地方。
  • 静态化改造就要要直接缓存 HTTP 链接。
  • 使用 nginx 等更擅长处理大并发静态文件的 web 服务请求做反向代理。

如何做动静分离:

  • URL 唯一化。
  • 分离浏览者相关的因素。
  • 分离时间因素。
  • 异步化地域因素。
  • 去掉 cookie。

动态数据处理方案:

  • ESI 方案:web 代理请求动态内容。服务端性能有影响,但是用户体验好。
  • CSI 方案:浏览器单独发起异步 JS 请求。服务端性能更好,但是用户端演示,体验稍差。

静态资源存储的方案:

  • 实体机单机部署。
    • 优点:没有网络瓶颈、能提升命中率,减少数据压缩和序列化、减少 cache 失效压力。
    • 缺点:物理机器浪费,提高了运维复杂度。
  • 统一 cache 层。
    • 优点:减少运维成本,方便接入其他静态化系统,共享内存,减少物理机成本。
    • 缺点:cache 内部交换网络瓶颈,不要存在单点。
  • 上 CDN
    • 优点:离用户近,效果更好。
    • 缺点:失效问题,命中率问题,发布更新问题。
    • 选择 CDN 二级 cache:
      • 靠近访问量比较集中的地区。
      • 离主站相对较远
      • 节点到主站间的网络好且稳定
      • 节点容量比较大。

4 03 二八原则:有针对性的处理好系统的“热点”

  • 热点数据
    • 静态热点数据,买家报名
    • 动态热点数据
      • 热点发现,异步系统分析数据后预热
      • 热点反馈,热点保护,热点数据隔离
  • 热点操作:限流、缓存热点数据。

5 04 流量削峰这事应该怎么做

削峰思路:

  • 排队:消息队列
  • 答题:防刷,延缓请求。
  • 分层过滤:过滤无效请求

6 05 影响性能的因素有哪些?又该如何提高系统的性能

性能指标:

  • QPS
  • RT

查看 CPU 瓶颈:JProfiler 和 Yourkit

7 06 秒杀系统“减库存”设计的核心逻辑

减库存操作:

  • 下单减库存:恶意下单
  • 付款减库存:超卖
  • 预扣减库存:
    • 缺点:恶意下单
    • 解决:买家打标,最大购买件数,重复下单不付款的操作次数进行限制。

大型秒杀推荐使用下单减库存的方式:

  • 通过事务保证减后库存不能为负数,否则就回滚。
  • 字节设置数据库字段为无符号整数,减后数据库字段小于 0 就报错。
  • 使用 case when 语句

    UPDATE item SET inventory= CASE WHEN inventory>=xxx THEN inventroy-xxx ELSE inventory END
    

减库存优化:

  • 使用 redis:适用简单场景
  • 使用 mysql:
    • 应用层排队:按照商品设置队列,单个商品为一个队列。
    • 数据库层排队:阿里做了 InnoDB 补丁。

8 07 准备 Plan B:如何设计兜底方案

  • 降级,非核心功能
  • 限流,
  • 拒绝服务

9 08 答疑解惑

Author: liushangliang

Email: phenix3443+github@gmail.com

Created: 2020-05-19 二 16:39