【系统设计】秒杀系统的设计思路

       还记得校招刚开始的时候,作为一个非科班、无实习经验、手上只有一个后台管理项目的渣渣来说,那面试真是一个酸爽,各种猛锤吊打啊。但是最后,自己还是拿到了几个offer?是什么原因呢?是运气吗?有可能,但其中还有一个重要原因就是我在校招后期花了一个星期,囫囵吞枣的跟着视频完成了一个秒杀项目,这个项目为自己面试加了不少分。你看,囫囵吞枣都有这种功效,说明这个项目还是很牛逼滴!!!其实秒杀的业务逻辑还是不复杂,就一个减库存,下订单,但中间处理高并发的一些思路与方法很值得我们在其他的场景中借鉴(不仅仅是编程哟),所以今天就大致讲讲秒杀设计的思路

秒杀场景的特点:

  • 高并发  ---> 逐层分流

  • 读多写少  ---> 使用缓存

应该考虑的问题:

  1. 高并发:短时间内大量请求(假设使用redis缓存,如果QPS超过了redis的承受范围(3~4W),缓存会被击穿,直接渗透到DB,从而击垮DB)

  2. 接口防刷:用户使用秒杀软件来请求,需过滤这些重复无效请求

  3. 秒杀url:提前知道秒杀url,绕过前端直接刷票

  4. 超卖:备货100,超卖200(秒杀价格都很低,超卖会严重影响公司利益)

  5. 数据库设计:秒杀有把数据库击垮的风险,尽量使秒杀业务的数据不和其他业务数据放在同一个数据库

针对上面问题的解决方案:

1. 秒杀页面静态化:将商品描述、图片等不会变化的信息写入到静态页面,用户请求时直接由前台客户端生成返回

2. 接口限流:

前端:用户点击秒杀按钮后,接下来的5秒内是不能点击的

后端:(1) 使用Redis中的Hash,key为商品id,field为userId,value为业务属性,过期时间需要根据实际业务和我秒杀人数决定,一般10秒

         (2) 令牌桶算法

3. 使用nginx服务器:nginx服务器是一个高性能web服务器,并发能力可达到几万,而tomcat只有几百。通过nginx映射客户端请求,再分发到后台tomcat服务器集群可以大大提高并发能力

4. redis预减库存:我们可以用redis来预减库存。预设一个库存值,使用redis的list结构,通过push和pop原子操作保证库存增减的原子性。如果库存已经没了,就直接返回抢购失败的提示。

5. 使用集群redis:考虑到缓存击穿问题,我们可以构建redis集群,采用哨兵模式,如果master挂了,可以自动切换到slave,提升redis的性能和可用性

6. 精简sql+乐观锁:我们在扣减库存时,我们可以将查库和更新操作合并成一个sql,并采用乐观锁机制,我们先查出版本号version,再执行更新语句:UPDATE  t_store  SET  store_count = store_count - 1, version = version + 1  WHERE  goods_id = ? AND version = ? AND store_count > 0;当范围结果为0时,有两种情况,一种是库存不足,返回提示消息给客户就行了,第二种就是乐观锁生效,返回消息给客户提示再进行一次(虽然肯定抢不到了)

7. 异步下单:经过限流,库存校验后,流入到这一步骤就是有效请求,为了提高下单效率,防止下单服务失败,我们将下单这一操作异步处理,最常用的就是使用消息队列,队列的优点是:异步,消峰,解耦;下单入库没问题后,我们就可以通知用户秒杀成功,如果失败,可以采用补偿机制重试

8. 服务降级:秒杀过程中出现某个服务器宕机,我们可以对服务进行熔断和降级

注意事项

1. redisCluster采用一hash一致性算法,所以不同的数据存在不同的redis节点上,所以当我们秒杀一个商品时,我们的数据请求是访问同一个redis节点。如果对于多个商品的秒杀,为了防止多个商品key落在同一redis节点,我们可以通过命令将不同的key强制放在不同的redis节点上

今天就讲这么多,太晚了要睡觉了,明天还要上班,虽然是在家远程上班,但还是不能“迟到”呀,希望疫情能快快变好,就算让我无偿加几天班我都愿意,嗯嗯,不能超过五天,超过了还是要给调休的。。。不开玩笑了,真心希望疫情快点过去,大家都能健康平安,中国加油,武汉加油,大家加油!

欢迎大家关注公众号:程序员进阶之路,里面记录了一个非科班程序员的成长之路

                                                       

发布了114 篇原创文章 · 获赞 199 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/qq_36582604/article/details/104219554