JAVA构建高并发商城秒杀系统——架构分析

面试场景
我们打算组织一个并发一万人的秒杀活动,1元秒杀1000个20元牙刷(某某商品),你给我说说解决方案。

秒杀/抢购业务场景
商品秒杀、商品抢购、群红包、抢优惠劵、抽奖、…

秒杀/抢购业务特点
秒杀商品价格低廉、一般是定时上架、持续时间短、瞬时并发量高…

秒杀、抢购技术特点
读多写少、高并发、资源冲突

知道这些,恭喜你,获得10分。

分析技术特点:

秒杀/抢购技术特点

1.读多写少

缓存

2.高并发

1.限流
2.负载均衡 (单体tomcat并发200完美胜任,突破五,六百就力不从心)
3.缓存
4.异步(将同步的并发请求转换为异步)
5.队列

3.资源冲突

数据库锁
分布式锁
其他原子操作
乐观锁
悲观锁
redis
decr
原子操作	
异步

回答到这里,恭喜你,获得50分了,但是还没有及格。

面试官: 我看你简历上写你做了个秒杀系统?我们就从这个项目开始吧,先介绍下你的项目。

关于项目介绍:如果有项目的话,技术面试第一步,面试官一般都是让你自己介绍一下你的项目。你可以从下面几个方向来考虑:
对项目整体设计的一个感受(面试官可能会让你画系统的架构图)
在这个项目中你负责了什么、做了什么、担任了什么角色
从这个项目中你学会了那些东西,使用到了那些技术,学会了那些新技术的使用
另外项目描述中,最好可以体现自己的综合素质,比如你是如何协调项目组成员协同开发的或者在遇到某一个棘手的问题的时候你是如何解决的又或者说你在这个项目用了什么技术实现了什么功能比如:用 redis 做缓存提高访问速度和并发量、使用消息队列削峰和降流等等。

我: 我说了我是如何考虑它的需求(秒杀地址隐藏,记录订单,减库存),一开始简单的用 synchronized 锁住方法,出现了问题,后来乐观锁改进,又有瓶颈,再上缓存,出现了缓存雪崩,于是缓存预热,错开缓存失效时间。最后,发现先记录订单再减库存会减少行级锁等待时间。

一面面试官很耐心地听,并给了我一些指导,问了我乐观锁是怎么实现的,我说是基于 sql 语句,在减库存操作的 where 条件里加剩余库存数>0,他说这应该不算是一种乐观锁,应该先查库存,在减库存的时候判断当前库存是否与读到的库存一样(可这样不是多一次查询操作吗?不是很理解,不过我没有反驳,只是说理解您的意思。事实证明千万别怼面试官,即使你觉得他说的不对)

面试官: 我缓存雪崩什么情况下会发生?如何避免?

我: 当多个商品缓存同时失效时会雪崩,导致大量查询数据库。还有就是秒杀刚开始的时候缓存里没有数据。解决方案:缓存预热,错开缓存失效时间

面试官: 问我更新数据库的同时为什么不马上更新缓存,而是删除缓存?

我: 因为考虑到更新数据库后更新缓存可能会因为多线程下导致写入脏数据(比如线程 A 先更新数据库成功,接下来要取更新缓存,接着线程 B 更新数据库,但 B 又更新了缓存,接着 B 的时间片用完了,线程 A 更新了缓存)

二面

面试官: 我们还是从你的项目开始吧,说说你的秒杀系统。

我: 一面时的套路。。。我考虑到秒杀地址在开始前不应暴露给用户。。。

面试官: 等下啊,为什么要这样呢?暴露给用户会怎么样?

我: 用户提前知道秒杀地址就可以写脚本来抢购了,这样不公平

面试官: 那比如说啊,我现在是个黑客,我在秒杀开始时写好了脚本,运行一万个线程获取秒杀地址,这样是不是也不公平呢?

我: 我考虑到了这方面,于是我自己写了个 LRU 缓存(划重点,这么多好用的缓存我为啥不用偏要自己写?就是为了让面试官上钩问我是怎么写的,这样我就可以逼逼准备好的内容了!),用这个缓存存储请求的 ip 和用户名,一个 ip 和用户名只能同时透过 3 个请求。

面试官: 那我可不可以创建一个 ip 代理池和很多用户来抢购呢?假设我有很多手机号的账户。

我: 这就是在为难我胖虎啊,我说这种情况跟真实用户操作太像了。。。我没法区别,不过我觉得可以通过地理位置信息或者机器学习算法来做吧。。。

面试官: 好的这个问题就到这吧,你接着说

我: 我把生成订单和减库存两条 sql 语句放在一个事务里,都操作成功了则认为秒杀成功。

面试官: 等等,你这个订单表和商品库存表是在一个数据库的吧,那如果在不同的数据库中呢?

我: 这面试官好变态啊,我只是个本科生?!?!我觉得应该要用分布式锁来实现吧。。。

面试官: 有没有更轻量级的做法?

我: 不知道了。后来查资料发现可以用消息队列来实现。使用消息队列主要能带来两个好处:(1) 通过异步处理提高系统性能(削峰、减少响应所需时间);(2) 降低系统耦合性。关于消息队列的更多内容可以查看这篇文章:https://snailclimb.gitee.io/javaguide/#/./system-design/data-communication/message-queue

后来发现消息队列作用好大,于是现在在学手写一个消息队列。

面试官: 好的你接着说项目吧。

我: 我考虑到了缓存雪崩问题,于是。。。

面试官: 等等,你有没有考虑到一种情况,假如说你的缓存刚刚失效,大量流量就来查缓存,你的数据库会不会炸?

我: 我不知道数据库会不会炸,反正我快炸了。当时说没考虑这么高的并发量,后来发现也是可以用消息队列来解决,对流量削峰填谷。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值