一、现公司解决秒杀方案:
1. 利用Redis原子性自增接口incr
2. Redis缓存 + 异步同步数据到数据库
优点:解决超卖问题,库存读写都在内存中,故同时解决性能问题。
缺点:由于异步写入DB,可能存在数据不一致。另可能存在少买,也就是如果拿到号的人不真正下订单,可能库存减为0,但是订单数并没有达到库存阀值。
二、秒杀过程:
Uid 和 prodid 非空判断
连接redis
拼接key
- 库存key
- 秒杀成功用户key
获取库存,如果库存null,秒杀还没有开始
判断用户是否重复秒杀操作:使用set集合数据结构存储
判断如果商品数量,库存数量小于1,秒杀结束
秒杀过程
- 库存-1: redis.decr(key)
- 把秒杀成功用户添加清单里面: redis.sadd(userkey,uid)
三、Redis事务:秒杀并发
(一)使用工具:ab测试
- CentOS 6默认安装
- CentOS 7 需要手动安装
(二)安装
- 联网: yum install httpd-tools
- 无网络:
(1) 进入cd /run/media/root/CentOS 7 x86_64/Packages(路径跟centos6不同)
(2) 顺序安装
apr-1.4.8-3.el7.x86_64.rpm
apr-util-1.5.2-6.el7.x86_64.rpm
httpd-tools-2.4.6-67.el7.centos.x86_64.rpm
(三)测试命令
vim postfile 模拟表单提交参数,以&符号结尾;存放当前目录。
内容:prodid=0101&
ab -n 2000 -c 200 -k -p ~/postfile -T application/x-www-form-urlencoded http://127.0.0.1:8081/Seckill/doseckill
(四)最常遇见的问题:
1. 超卖问题 :
解决方案:通过乐观锁解决,缺点:存在库存遗留库存及连接超时
2. 连接超时: connect-timeout
解决方案:连接池
3. 连接限制:connection-refused
解决方案:ab测试增加-r参数:
ab -n 2000 -c 100 -r -p postfile -T 'application/x-www-form-urlencoded' http://127.0.0.1:8080/seckill/doseckill
4. 库存遗留问题:已经秒光,可是还有库存
乐观锁造成的问题,先点的没秒到,后点的可能秒到了
解决方案: LUA脚本,通过lua脚本解决争抢问题,实际上是redis 利用其单线程的特性,用任务队列的方式解决多任务并发问题
(五)常见秒杀解决方案:
1、前端方案:
A:扩容
加机器,这是最简单的方法,通过增加前端池的整体承载量来抗峰值。
B:静态化
将活动页面上的所有可以静态的元素全部静态化,并尽量减少动态元素。通过CDN来抗峰值。
C:限流
一般都会采用IP级别的限流,即针对某一个IP,限制单位时间内发起请求数量。
或者活动入口的时候增加游戏或者问题环节进行消峰操作。
D:禁止重复提交:用户提交之后按钮置灰,禁止重复提交
F:有损服务
最后一招,在接近前端池承载能力的水位上限的时候,随机拒绝部分请求来保护活动整体的可用性。
2、后端方案:
缓存 + 队列
Redis是一个分布式缓存系统,支持多种数据结构,我们可以利用Redis轻松实现一个强大的秒杀系统。
利用redis记录读取实时库存。一旦库存不足,立即抛出异常。反馈给前端。如果库存足够,通过rpc调用通知订单微服务系统生成订单。得到订单系统的生成成功的反馈以后,在秒杀微服务系统中生成一个本地订单记录,在数据库增销量减库存。
Redis 提供了 INCR/DECR/SETNX 命令,把RMW三个操作转变为一个原子操作
Redis 是使用单线程串行处理客户端的请求来操作命令,所以当 Redis 执行某个命令操作时,其他命令是无法执行的,这相当于命令操作是互斥执行的
四、Redis可能存在的问题:
缓存穿透:
1、应用服务器压力变大了
2、redis命中率降低
3、一直查询数据库
- 缓存穿透现象:
1、redis查询不到数据
2、出现很多非正常url访问
- 缓存穿透解决方案:
1、对空值缓存(临时方案)
2、设置可访问的名单(白名单):bitmap位操作,缺点:效率不是很高
3、采用布隆过滤器,缺点:命中率不是很准备
4、进行实时监控
缓存击穿:
1、数据库访问压力瞬时增加
2、redis里面没有出现大量key过期
3、redis正常运行
- 缓存击穿现象;
1、redis某个key过期了,大量访问使用这个key
- 缓存击穿解决方案:
1、预先设置热门数据
2、实时调整
3、使用锁 缺点:降低效率
缓存雪崩:
1、数据库压力变大,服务器崩溃
2、在极少时间段,查询大量的key的集中过期情况
- 缓存雪崩解决方案:
1、构建多级缓存架构 ; Nginx + redis + 其它缓存(ehcache)
2、使用锁和队列
3、设置过期标志更新缓存
4、将缓存失效时间分散开
三十六般武艺,七十二般变化,修练出个人品牌并发出光芒