没有高并发经验,却被问到如何设计一个秒杀场景,该怎么办

消息队列除了在解耦、异步场景之外,最大的作用场景是用于流量削峰,面对海量流量请求,可以将这些请求数据用异步的方式先存放在消息队列中,而消息队列一般都能够存储大量消息,消息会被消费端订阅消费,这样就有效地将峰值均摊到其他时间进行处理了。

没有高并发经验,却被问到如何设计一个秒杀场景,该怎么办?

如上,消息队列就像我们平常见到的水库一样,当洪水来临时,拦住并对其进行储蓄,以减少对下游的冲击,避免了洪水的灾害。

目前有大量优秀的开源消息队列框架,如 RocketMQ、Kafka 等,而我之前在中通时主要负责消息平台的建设与维护工作,中通每天面对几千万的订单流量依然那么稳固,其中消息队列起了很大的“防洪”作用!

2、答题

除了利用消息队列对请求进行“储蓄”达到削峰的目的之外,还可以通过在用户发起请求前,对用户进行一些校验操作,比如答题、输入验证码等等,这种答题机制,除了可以防止买家在秒杀过程中使用作弊脚本之外,在秒杀场景中最主要的作还是将请求分散到各个时间点,秒杀场景一般都是集中在某个点进行,比如 0 点时刻,如果没有答题机制,几乎所有的流量都在 0 点时刻涌入服务器中,如果有答题机制,就能延缓用户的请求,从而达到请求分散到各个时间点的目的。

如何保持一致性?

========

秒杀场景,本质上就是在海量买家同时请求购买时,能够准确并将商品卖出去。

在秒杀的高并发读写请求过程中,需要保证商品不会发生“超卖”现象,因为秒杀的商品是数量一定的,但会有成千上万个用户在同一时间下单购买,在减扣库存过程中如何保证商品数量的准确性至关重要。

减扣库存方案分析

========

我在以前在做秒杀项目的时,分析过几种减扣库存的方式,我简单分析下。

1、下单减扣库存

买家只要完成下单,立即减扣商品库存,这种方式实现是最简单而且也是最精准的,通常可以在下单时利用数据库事务能力即可保证减扣库存的准确性,但需要考虑买家下单后不付款的情况。

2、付款减扣库存

即买家下单后,并不立即减库存,而是等到有用户付款后才真正减库存,否则库存一直保留给其他买家。但因为付款时才减库存,如果并发比较高,有可能出现买家下单后付不了款的情况,因为可能商品已经被其他人买走了。

当只有买家下单后,并且已完成付款,才执行库存的减扣,这种方式好处是避免了买家不付款导致实际没有卖出这么多商品的情况,但这种方式会造成用户体验不好,因为这会导致有些用户付款时商品有可能被人买走了导致付款失败的问题。

3、预扣库存

这种方式结合以上两种方式的优点,当买家下单后,预扣库存,只会其保留一定的时间,比如 10 分钟,在这段时间内如果买家不付款,则将库存自动释放,其它买家可以继续抢购。这种做法需要买家付款前,再做一次商品库是否还有保留,如果没有保留,则再次尝试预扣,预扣失败则不允许继续付款;如果有保留,付款完成后执行真正的减扣库存动作。

但预扣库存依然没有彻底解决减扣库存链路中存在的问题,比如有些买家可以在释放的瞬间立马又重新下单一次,相当于将库存无限地保留下去,因此我们还需要将记录用户下单次数,如果连续下单超过一定次数,或者超过下单并不付款次数,就拦截用户下单请求。

总结:

一般最简单的做法就是使用下单减库存的方式(我之前的项目中就是用的这种),我当初的考虑是因为在秒杀场景中,商品的性价比通常很高,秒杀就是创造一种只有少量买家能买到的场景,一般来说买家只要“秒”到商品了,极少情况会出现退款的,即使发生了少量退款,造成实际卖出去的商品会比数据上少,也是可以通过候补来解决。

如何减扣库存?

=======

减扣库存动作应该放在哪里执行?

下面我具体分析一下减扣库存的几种实现方式:

  1. 如果链路涉及的逻辑比较简单的,比如下单减库存这种方式,最简单的做法就是在下单时,利用数据库的本地事务机制进行对库存的减扣,比如使用 where 库存 >0不满足就回滚;

  2. 将库存数量值放在缓存中,比如 Redis,并做持久化处理。

需要注意的是,如果遇到减扣库存的逻辑很复杂,比如减扣库存之后需要在同一个事务中做一些其他事情,那么就不能使用第二种方式了,只能使用第一种方式在数据库层面上面操作,以保证同在一个事务中。面对这种情况,你可以将热点数据进行数据库隔离,把这些热点商品单独放在一个数据库中。

如何实现高可用性?

=========

最后,为了保证秒杀系统的高可用性,必须要对系统进行兜底处理,以便遇到极端的情况系统依然能够运转,通常的做法有服务降级、服务限流、拒绝请求等方式处理。

服务降级

====

当请求量达到系统承受的能力时,需要对系统的一些非核心功能进行关闭操作,尽可能将资源留给秒杀核心链路。

比如在秒杀系统中,还存在其他非核心的功能,我们可以在系统中设计一些动态开关,比如在网关层在路由开关,将这些非核心的请求直接在最外层拒掉。

还有就是对页面展示的数据进行精简化,用降低用户体验换取核心链路的稳定运行。

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
img

最后

针对最近很多人都在面试,我这边也整理了相当多的面试专题资料,也有其他大厂的面经。希望可以帮助到大家。

下面的面试题答案都整理成文档笔记。也还整理了一些面试资料&最新2021收集的一些大厂的面试真题(都整理成文档,小部分截图)

在这里插入图片描述

最新整理电子书

在这里插入图片描述

下面的面试题答案都整理成文档笔记。也还整理了一些面试资料&最新2021收集的一些大厂的面试真题(都整理成文档,小部分截图)

[外链图片转存中…(img-zjbTuMHx-1711176872195)]

最新整理电子书

[外链图片转存中…(img-G5JorVTy-1711176872196)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值