总体思路:
尽量将请求拦截在系统上游
读多写少的场景多使用缓存
分布式的在Redis存参与用户的ID 然后同步记录去重 再随机抽100个
参与用户指秒杀开始后dt时间段内提交请求的用户
然后前端随机丢点请求 再做好反脚本
其实也是公平的 而且应该比“凭手速”更公平 因为如果完全按到达服务器的时间算 有太多用户不可控但短期内不改变的因素会影响成功率 比如网速 设备性能
丢弃订单,最早期,量太大扛不住,直接前端随机reject一些,返回给抢单失败,简单粗暴,但是有效
前端层----协议层(nginx)----- 缓存层------后端逻辑层------消息队列----------开始具体业务处理
---------------拦截恶意请求-----
问题:
1、高并发:
redis顶住?缓存雪崩、击穿、穿透
2、超卖:
3、恶意请求:
4、链接暴露:
5、数据库
办法:
单一职责
高并发 ======= 服务设计单一职责,单独设计一个秒杀服务,有助于扩容。
数据库 ======= 为了防止秒杀打挂数据库影响其他业务,单独设计一个秒杀表。
链接暴露 ====== 秒杀链接加盐,MD5之类的加密算法加密随机的字符串去做url,然后通过前端代码获取url后台校验才能通过。
redis ======= 集群、主从同步、读写分离、哨兵,开启持久化
nginx ======= 负载均很,临时加很多台秒杀服务器;拦截恶意请求(请求次数太夸张,对单个ip每秒访问次数加限制、加黑名单)
cdn预热 ========= 一些秒杀相关的静态文件可以先推到cdn
按钮置灰 ======== 活动开始前:前端定时检测当前时间,到点了就取消置灰;js限制用户几秒之内只能点击一次
前段限流 ========== 按钮置灰
预热 ========== 先把库存商品加载到redis,结束后再异步修改数据库
服务降级 ========= 用户抢到即为成功,订单具体处理异步去操作
削峰填谷 ======== MQ(设置定长队列)
临时提高宽带
redis并发争抢 ======== Lua:
Lua 脚本功能是 Reids在 2.6 版本的最大亮点, 通过内嵌对 Lua 环境的支持, Redis 解决了长久以来不能高效地处理 CAS (check-and-set)命令的缺点, 并且可以通过组合使用多个命令, 轻松实现以前很难实现或者不能高效实现的模式。
Lua脚本是类似Redis事务,有一定的原子性,不会被其他命令插队,可以完成一些Redis事务性的操作。这点是关键。
知道原理了,我们就写一个脚本把判断库存扣减库存的操作都写在一个脚本丢给Redis去做,那到0了后面的都Return False了是吧,一个失败了你修改一个开关,直接挡住所有的请求,然后再做后面的事情嘛。
这个为啥要做呢,不怕一万就怕万一,万一你真的顶不住了,限流,顶不住就挡一部分出去但是不能说不行,降级,降级了还是被打挂了,熔断,至少不要影响别的系统,隔离,你本身就独立的,但是你会调用其他的系统嘛,你快不行了你别拖累兄弟们啊。
原文:https://www.cnblogs.com/kbian/p/12284963.html