秒杀项目总结

秒杀项目总结

秒杀总结参考
牛客秒杀总结
在这里插入图片描述

0、简单讲一下高并发的秒杀系统

这个系统的基本框架是黑马程序员的瑞吉外卖项目,在实现外卖项目的所有功能业务之后,在此基础上,改进了添加了高并发的秒杀功能。通过根据场景不断的迭代秒杀成为支持高并发的高性能系统。为了解决秒杀场景下的高并发问题,进行了一些几种手段的优化:
1、引入Redis作为缓存中间件,主要作用是缓存预热、预减库存等。
2、页面优化,缓存到浏览器,前后端分离降低服务器压力,加快访问速度。
3、安全性上,使用双重MD5加密,隐藏秒杀接口,设置限流防刷,数学公式验证防刷。
4、Jmeter压测秒杀接口,系统QPS从50/s提升到500/s。

0、秒杀系统面临的问题?

  • 高并发场景
  • 超卖、重复下单的问题
  • 脚本恶意访问
  • 数据库频繁交互扛不住
  • 加了缓存之后缓存的三大问题(击穿、穿透、雪崩)

Redis来判断是否符合秒杀请求的下单资格,符合的话在redis中进行库存预减,同时将此消息放入消息队列,消息队列的消费者负责从队列中获取消息进行消费(执行真正的生成订单、操作数据库减库存的操作)
保证不出错的点:
1、redis减库存和消息生成一对一
2、消息队列必须保证消息的完整消费
3、

1、秒杀中超卖问题

在Redis中预减库存时利用redis的单线程特性处理秒杀超卖问题!

实现流程:

  • 系统初始化时,将秒杀商品的库存量预先加载存储到redis中(缓存预热)
  • 秒杀请求接收到的时候,在redis中进行预减库存(decrement),库存不足时,秒杀失败,判断大于0时进行下面操作。(decrement、increment)为原子操作,线程安全。
  • 将请求的用户实体和秒杀的商品实体序列化之后放入异步队列(消息中间件发送),返回秒杀排队中。
  • 服务端消息接收器进行消息的消费,也就是要不队列的出队,然后将消息反序列化为实体,执行数据库的减库存,并生成订单,返回订单详情。
在数据库库存减1时,依靠MySQL中的排它锁实现。
boolean result = seckillGoodsService.update(new UpdateWrapper<SeckillGoods>().setSql("stock_count ="+
                "stock_count-1").eq("id",seckillGoods.getId()).gt("stock_count",0));

2、减库存成功,订单生成失败怎么办?

非分布式系统中使用Springboot提供的事务功能即可。
分布式系统事务:将减库存与生成订单操作组合为一个事务。要么一起成功,要么一起失败。分布式事务方案

3、限流削峰的措施?

  • 令牌桶算法接口限流
  • 线程池技术限制并发数
  • 数学公式验证码防刷功能

令牌桶算法:
令牌桶算法和漏桶算法不同的是,有时后端能够处理一定的突发情况,只是为了系统稳定,一般不会让请求超过正常情况的60%,给容灾留有余地。但漏桶算法中后端处理速度是固定的,对于短时的突发情况,后端不能及时处理,和实际处理能力不匹配。

令牌算法是以固定速度往一个桶内增加令牌,当桶内令牌满了后,就停止增加令牌。上游请求时,先从桶里拿一个令牌,后端只服务有令牌的请求,所以后端处理速度不一定是匀速的。当有突发请求过来时,如果令牌桶是满的,则会瞬间消耗桶中存量的令牌。如果令牌还不够,那么再等待发放令牌(固定速度),这样就导致处理请求的速度超过发放令牌的速度。

如下图,灰色部分是令牌桶,有容量限制,只能最多存放 capacity 个令牌,每秒以固定的速度向桶中增加令牌,如果桶的容量满了,则等待桶中令牌被消耗后,再增加令牌。另一边应用进程拿到令牌后才处理请求,如果没有拿到令牌,则不处理该请求。

在这里插入图片描述
1 有一个固定容量的桶存放令牌(Token)。

2 桶初始化是空的,以固定的速度(rate)向桶里填充 Token,当达到桶的容量时,多余的令牌被丢弃。

3 当请求到来时,从桶里移除一个令牌,如果没有令牌,则拒绝该请求。

令牌桶控制的是令牌入桶的速度,对于拿到令牌的速度没有限制,允许一定的突发流量被瞬间处理。

4、安全性问题

  • 封IP,nginx中可以设置单个ip访问频率和次数多了有拉黑操作
  • 隐藏秒杀接口地址
  • 验证码防止恶意刷

5、多机器扣减库存,如何保证线程安全?

多机器意味着分布式场景,此时的redis肯定是分布式的,有多台redis服务器,可以用分布式锁来解决这个问题,具体实现可以用redission客户端实现。
redis分布式锁详见另一篇文章redis分布式锁的进化

6、缓存类问题:

缓存失效问题详解:缓存失效的问题及持久化

  • 缓存数据突然全部失效,导致请求全部打到数据库,如何解决?(缓存雪崩)
    答案:典型的缓存雪崩问题,给缓存中的数据的过期时间加随机数。
  • 热点数据失效问题如何解决?(缓存击穿)
    答案:设置热点数据永远不过期。

7、Redis突然挂掉,如何减轻数据库压力?

Redis集群模式:主从模式、哨兵模式、集群模式

主从模式:

主机宕机,主机断开,从机升级为主机。

哨兵模式:

每个sentinel会向其它sentinel、master、slave定时发送消息(哨兵定期给主或者从和slave发送ping包(IP:port),正常则响应pong,ping和pong就叫心跳机制)如果发现消息在指定时间内没有回复,则判定主机为宕机,判定死亡之后,通过选举算法,从剩下的slave节点中选举产生新的主节点,自动配置同步问题。

8、分布式会话的问题?

分布式会话可以通过session、cookie或者token的手段来解决,解析请看
在我的秒杀项目中,采用的session的方式来解决这个登录问题,不同的浏览器、不同的用户、不同的电脑访问服务端时会生成不同的sessionid,传回给浏览器,存放在cookie中。二次登录时,从请求中获取到sessionid并判断是否存在,如果存在,则说明已经登录,可以进行其他操作,如果不存在,则说明未登录或者登录失效,重新登录。这些判断操作等处理在服务端的拦截器中进行。

9、项目中redis和rabbitmq的作用

redis

redis中库存减成功后,生成一条消息包含了商品信息、用户信息消息由MQ的生产者生产,经由queue模式发送给消费方,即订单生成的业务模块,在该模块会消费这条消息,根据其中的信息进行订单的生成,以及数据库的修改操作。
运用三级存储:内存、redis、数据库

  • 作为缓存中间件提升系统性能
  • 预减库存,防止超卖功能实现
  • redis设置热点数据永不过期
rabbitmq(rabbitmq可以看其他系列文章)

作为异步下单的中间件,利用队列排队下单缓解数据库的并发压力。

10、线程池的应用

线程池的线程数的设置经验:

设置最大线程数来限制浪涌流量

  • CPU密集型业务:N+1
  • IO密集型业务:2N+1
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智博的自留地

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值