主要问题:并发读、并发写

关键点

  • 高性能
  • 一致性
  • 高可用

原则

  • 请求数据要尽量少
    • 减少序列化和反序列化
    • 字符转化
  • 请求数要尽量少
    • 如在请求路径上将多个 Javascript 用逗号合并,服务端一次性返回多个文件
  • 路径要尽量短
    • 将多个相互强依赖的应用合并部署到一起
  • 依赖要尽量少
    • 可以把依赖的服务先降级或停用
  • 不要有单点
    • 将服务无状态化,让实例可以动态伸缩
    • 把秒杀系统独立出来单独打造一个系统,并且在系统部署上也独立做一个机器集群,避免影响非秒杀商品的机器

动静分离

  • 根据情况把静态数据缓存到离用户近的地方(浏览器、CDN、服务端的 Cache)
  • 直接缓存 HTTP 连接
  • 怎么做:
    • URL 唯一化(如 /id=xxx)
    • 分离浏览者相关的因素(比如登录信息,这些通过动态请求获取)
    • 分离时间因素,也通过动态请求获取
    • 异步化地域因素
    • 去掉 Cookie(让缓存的静态数据中不含有 Cookie)
    • 服务端:
      • 生成完整页面
      • 客户端获取动态内容
  • 架构方案
    1. 实体机单机部署:大 Cache 容量,高缓存命中率
    2. 统一 Cache 层
    3. 上 CDN:二级 Cache(一级发现没缓存数据就去二级找,都没有就回源获取数据并缓存到一级、二级缓存)

热点数据

  • 静态热点数据:能提前预测的
    • 通过商业手段(强制让商家登记、对买家每天访问的商品进行大数据计算)
  • 动态热点数据:不能提前预测的
    • (异步)收集交易链路上各个环节中的中间件产品的热点 Key(Nginx、缓存、RPC 服务框架等)
    • 上报热点,透传给下游系统

流量削峰

  • 排队
  • 答题:延缓请求,并可以防止买家使用秒杀器作弊
  • 分层过滤:只在写数据时进行强一致性校验

性能优化

  • 影响:
    • 减少线程等待时间影响不大
    • 减少 CPU 执行时间影响大
    • 线程数影响大
  • 发现瓶颈:
    • 工具:JProfiler、Yourkit
    • CPU 使用率超过 95%
  • 优化方式:
    • 减少编码
    • 减少序列化
    • Java 极致优化(直接输出流数据、直接使用 Servlet 处理请求)
    • 并发读优化

减库存

  1. 下单减库存:恶意下单
  2. 付款减库存:超卖
  3. 预扣库存(最常见):同样可能恶意下单(影响小一些),确保最终一致性

Plan B

  • 降级
  • 限流:客户端限流、服务端限流
  • 拒绝服务