|
1 | | -## 解决思路 |
2 | | -尽量将请求拦截在数据库的上游,因为一旦大量请求进入数据库,性能会急剧下降 |
| 1 | +## 业务上适当规避 |
| 2 | +1. 根据某些规则对部分用户直接返回没抢到。比如有些用户曾经被系统识别为恶意用户、垃圾用户、僵尸用户,直接告诉用户已经抢完 |
| 3 | +2. 分散不同客户端打开活动入口的时间。比如将1秒内的流量分散到10秒 |
3 | 4 |
|
4 | | -## 架构和实现细节 |
| 5 | +## 技术上硬核抗压 |
| 6 | +1. 限流策略。比如在压力测试中我们测到系统QPS达到了极限,那么超过的部分直接返回已经抢完,通过Nginx的lua脚本可以查redis看到QPS数据从而可以动态调节 |
| 7 | +2. 异步削峰。对Redis中的红包预减数量,立即返回抢红包成功请用户等待,然后把发送消息发给消息队列,进行流量的第二次削峰,让后台服务慢慢处理 |
| 8 | +3. 服务逻辑。比如业务逻辑是使用事务控制对数据库的创建订单记录,减库存的操作,那么创建操作要放到减库存操作之前,从而避免减数量update的行锁持有时间 |
| 9 | +4. 机器配置。当然是服务器机器配置约高越好,数据库配置越猛越好,高并发抢红包主要是CPU与网络IO的负载较高,要选择偏向CPU与网络IO性能的机器 |
| 10 | + |
| 11 | +### 架构和实现细节 |
5 | 12 | * 前端模块(页面静态化、CDN、客户端缓存) |
6 | 13 | * 排队模块(Redis、队列实现异步下单) |
7 | 14 | * 服务模块(事务处理业务逻辑、避免并发问题) |
8 | | -* 防刷模块(验证码、限IP) |
| 15 | +* 防刷模块(验证码、限制用户频繁访问) |
9 | 16 |
|
10 | | -## 模块解析 |
11 | | -### 前端模块 |
| 17 | +### 模块解析 |
| 18 | +#### 前端模块 |
12 | 19 | 1. 页面静态化,将后台渲染模板的方式改成使用HTML文件与AJAX异步请求的方式,减少服务端渲染开销,同时将秒杀页面提前放到CDN |
13 | 20 | 2. 客户端缓存,配置Cache-Control来让客户端缓存一定时间页面,提升用户体验 |
14 | 21 | 3. 静态资源优化,CSS/JS/图片压缩,提升用户体验 |
15 | 22 |
|
16 | | -### 排队模块 |
| 23 | +#### 排队模块 |
17 | 24 | 1. 对Redis中的抢购对象预减库存,然后立即返回抢购成功请用户等待,这里利用了Redis将大部分请求拦截住,少部分流量进入下一阶段 |
18 | 25 | 2. 如果参与秒杀的商品太多,进入下一阶段的流量依然比较大,则需要使用消息队列,Redis过滤之后的请求直接放入到消息队列,让消息队列进行流量的第二次削峰 |
19 | 26 |
|
20 | | -### 服务模块 |
| 27 | +#### 服务模块 |
21 | 28 | 1. 消息队列的消费者,业务逻辑是使用事务控制对数据库的下订单,减库存操作,且下订单操作要放到减库存操作之前,可以避免减库存update的行锁持有时间 |
22 | 29 |
|
23 | | -### 防刷模块 |
| 30 | +#### 防刷模块 |
24 | 31 | 1. 针对恶意用户写脚本去刷,在Redis中保存用户IP与商品ID进行限制 |
25 | 32 | 2. 针对普通用户疯狂的点击,使用JS控制抢购按钮,每几秒才能点击一次 |
26 | 33 | 3. 在后台生成数学计算型的验证码,使用Graphics、BufferedImage实现图片,ScriptEngineManager计算表达式 |
27 | 34 |
|
28 | | -### 异常流程的处理 |
| 35 | +#### 异常流程的处理 |
29 | 36 | 1. 如果在秒杀的过程中由于服务崩溃导致秒杀活动中断,那么没有好的办法,只能立即尝试恢复崩溃服务或者申请另寻时间重新进行秒杀活动 |
30 | 37 | 2. 如果在下订单的过程中由于用户的某些限制导致下单失败,那么应该回滚事务,立即告诉用户失败原因 |
31 | 38 |
|
32 | | -## 难点+坑+复盘优化 |
33 | | -### 难点 |
34 | | -1. 理解整个架构设计的思路,围绕这个思路进行思考有什么方式可以做到,在开发过程中多进行压力测试反馈优化 |
35 | | -2. 代码中异常情况的处理与业务上应急预案的准备 |
| 39 | +### 难点+坑+复盘优化 |
| 40 | +#### 原则 |
| 41 | +业务优化思路:业务上适当规避 |
| 42 | +技术优化思路:尽量将请求拦截在数据库的上游,因为一旦大量请求进入数据库,性能会急剧下降 |
| 43 | +架构原则:合适、简单、演化 |
| 44 | + |
| 45 | +## 难点 |
| 46 | +1. 将高并发大流量一步步从业务和技术方面有条不紊地应对过来 |
| 47 | +2. 代码中异常情况的处理与应急预案的准备 |
36 | 48 |
|
37 | | -### 坑 |
| 49 | +## 坑 |
38 | 50 | 1. 以上的解决方案能通过利用Redis与消息队列集群来承载非常高的并发量,但是运维成本高。比如Redis与消息队列都必须用到集群才能保证稳定性,会导致运维成本太高。所以需要有专业的运维团队维护。 |
39 | 51 | 2. 避免同一用户同时下多个订单,需要写好业务逻辑或在订单表中加上用户ID与商品ID的唯一索引;避免卖超问题,在更新数量的sql上需要加上>0条件 |
40 | 52 |
|
41 | | -### 优化 |
| 53 | +## 优化 |
42 | 54 | 1. 将7层负载均衡Nginx与4层负载均衡LVS一起使用进一步提高并发量 |
43 | 55 | 2. 以上是应用架构上的优化,在部署的Redis、消息队列、数据库、虚拟机偏向选择带宽与硬盘读写速度高的 |
44 | 56 | 3. 提前预热,将最新的静态资源同步更新到CDN的所有节点上,在Redis中提前加载好需要售卖的产品信息 |
|
0 commit comments