场景
你的商城正在策划了一期秒杀活动,活动在第五天的 00:00 开始,仅限前 200 名,那么秒杀即将开始时,后台会显示用户正在疯狂地刷新 APP 或者浏览器来保证自己能够尽量早的看到商品。
现象
- 只有固定人数的人可以购买成功
- QPS典型的瞬间波峰
- 用户对请求结果延迟感稍微放宽松
面对的挑战
- 现有业务的影响(独立域名、服务解决)
- 高并发时,应用服务器和数据库压力
- 超卖,卖出产品数量多于已有数量
- 刷单,每个用户抢到多个订单
- 无效刷新点击,用户在系统卡顿时,会进行连续点击
- 时延 ,需要2-3s内返回结果,不能直接返回404
设计核心关注点
- 有效数据总是少量,需要在上层拦截住大部分无效数据
- 使用队列,进行异步处理、解耦合、削峰填谷
数据流向图
image.png各个层次优化方案
1 浏览器层面
- 按钮置灰
- 限时提交一次,x秒内只允许提交一次请求
- 页面内容静态化
- 下单URL动态化
2 Nginx层面
- 由于登录属性,可对uid做请求计数和去重,限制访问次数,做页面缓存。(分布式中同uid多后端无法去重)
3 业务服务层面
- 通过队列只接受固定请求数,每次透传固定数量到数据层进行请求
- 多于固定数的请求,直接返回秒杀完毕
- 业务逻辑异步,比如下单业务、支付业务、统计数据业务等
4 数据层面
- 悠哉悠哉的工作即可
Q&A
1 架构中,其实压力最大的反而是站点层,假设真实有效的请求数有1000万,不太可能限制请求连接数吧,那么这部分的压力怎么处理?
- 站点层是可以通过加机器扩。
- 如果机器不够,进行降级,避免整个系统崩溃。
2 “控制了10w个肉鸡,手里有10w个uid,同时发请求” 这个问题怎么解决哈?
- 服务层写请求队列控制
3 如果队列处理失败,如何处理?肉鸡把队列被撑爆了怎么办?
- 队列失败概率很低。最坏的情况下,缓存了若干请求之后,后续请求都直接返回“结束”
4 站点层过滤的话,怎么处理多台服务器集群经过负载均衡器将相同用户的响应分布到不同服务器的情况呢?还是说将站点层的过滤放到负载均衡前?
- 在nginx层做负载均衡,让一个uid的请求尽量落到同一个机器上
5 不同的用户浏览同一个商品 落在不同的缓存实例显示的库存完全不一样 请问怎么做缓存数据一致或者是允许脏读?
- 目前的架构设计,请求落到不同的站点上,数据可能不一致(页面缓存不一样),这个业务场景能接受。但数据库层面真实数据是没问题的。
网友评论