44 | 记一次双十一抢购性能瓶颈调优
44 | 记一次双十一抢购性能瓶颈调优
讲述:李良
时长15:48大小10.85M
抢购业务流程
抢购系统中的性能瓶颈
1. 商品详情页面
2. 抢购倒计时
3. 获取购买资格
4. 提交订单
5. 支付回调业务操作
性能瓶颈调优
1. 限流实现优化
2. 流量削峰
3. 数据丢失问题
总结
思考题
赞 9
提建议
精选留言(32)
- zk_2072019-10-27超哥,你们订单超时是基于定时任务去做的吗?比如我订单是3min有效,怎么保证3min没支付就取消?
作者回复: 我们是放在mq中去实现的,rabbitmq中有一个延时队列,当过期时间到了,就会被放到死信队列中,只要去死信队列中实时消费就好了。 定时任务也是一种实现方式,在分布式部署定时任务时,要实现分布式定时任务。
共 4 条评论14 - -W.LI-2019-08-31课后思考题: 文中老师讲了预扣库存可以多放开一点。比如实际只有100件商品,允许预扣300。支付成功后扣去真实库存。之前某包买东西,就遇见过了几天客服联系说没货了退款这种。我之前做过一个是支付完真实库存扣件失败,直接退款回滚数据的。 恶意用户刷单的话可以对用户进行封号处理,在redis中缓存用户待带支付的订单数,每次进入带支付前校验下待支付的集合里有多少(金额数目都可)。判定为恶意刷单的直接黑名单。某东用的好像是黑名单。展开
作者回复: 不是预扣库存多放开,是在预扣库存前设置一个购买资格,购买资格是300,预扣库存还是100不变。不会出现商品超卖的问题。 问答题回答思路很好。
共 3 条评论10 - 阿卧2020-03-16扣件库存用分布式锁,性能瓶颈就在分布式锁上。那么如何优化提高下单的qps呢?
作者回复: 使用更优的分布式锁,以及细化锁粒度,例如将一个库存分为多个库存等
共 2 条评论7 - 王三好2019-11-18队列使用什么实现的
作者回复: 有界队列LinkedBlockingQueue或者Disruptor实现队列
7 - 超威丶2019-08-31没有比较好的办法,如果等到付款才扣减库存,可能会出现超卖!一般好的办法限制一个账户买同个商品的数量,减少损失
作者回复: 没有直接的解决方案,但是我们可以通过间接的方案来减少这种恶意锁单的问题。建立信用以及黑名单机制,首先在获取购买资格时将黑名单用户过滤掉,其次在获取购买资格后,信用级别高的用户优先获取到库存。用户一旦恶意锁单就会被加入到黑名单。
共 2 条评论7 - zk_2072019-10-24您好,请问本文中说的订单幂等性校验如何控制吗?还有就是库存放在缓存中,DB和缓存如何保证一致性?能说下解决方案吗?
作者回复: 通过分布式锁来控制的,在下单时,以缓存中的库存为准,不会修改DB中的库存,只有在支付完成之后,回调时去数据库中扣除库存,严格上来说,只要业务操作没有bug,两者的库存就是一致的
5 - -W.LI-2019-08-31当请求的 key 值放入到队列中,请求线程进入阻塞状态,当线程从队列中获取到请求线程的 key 值时,就会唤醒请求线程获取购买资格。 老师好!能讲下写读请求使用队列缓存的原理么? 之前有看过servlet3.0的和这个是不是有点像。客户端的链接是阻塞的,服务端通过队列缓存,处理完以后通过之前的链接把数据写回给客户端。 servlet3.0是servlet规范,我现在基本用的都会spring自带的dispa***。如果要实现这总异步IO需要我们自己实现servlet是么? IO方面的知识很薄弱,netty好像很经典可是从来没看过,一方面觉得自己菜,领一方面就是工作中没用上,我从下手。希望老师给点学习指南谢谢。 依依不舍(´..)❤展开5
- zk_2072019-10-25超哥,请教个问题,就是秒杀的时候我们一般是下单预扣减库存,比如10分钟之后如果没有支付的话库存回流,这时候怎么保证库存准确性与系统性能呢?
作者回复: 我们是通过一个生产者消费者的方式实现缓存库存的添加和删除,并且通过分布式锁来保证原子性
4 - torres2020-10-26性能调优黄金法则 缓存 限流 异步 解耦 补偿展开3
- 钱2019-09-12课后思考及问题 1:在提交了订单之后会进入到支付阶段,此时系统是冻结了库存的,一般我们会给用户一定的等待时间,这样就很容易出现一些用户恶意锁库存,导致抢到商品的用户没办法去支付购买该商品。 首先,感觉老师的问题有点奇怪,没明白“某些用户恶意锁库存,导致抢到商品的用户没办法去支付购买该商品的”——我的理解,300个人抢到了抢购的商品,实际只有100个,如果是先款订单,谁先付款谁就先实际抢购到对应的商品呗!如果担心付款后,不要了要求退货,这就是另外的事情了,一般而言待抢购的商品都是物超所值的,需要担心的应该是多抢。 如果是要控制有购买资格的人数,可以利用大数据用户画像的方式,将级别高信用好的用户优先放过去,当然,黑名单也用起来过滤掉恶意用户,再者就是限制用户购买的商品数量。展开
作者回复: 是的
3 - asura2020-01-30课后思考题:设置黑名单来防止恶意锁库存。 下单前会有很多检验性的判断,而且会经常变动,可以采用责任链模式,动态添加检验逻辑。在链头判断用户是不是黑名单,是的话就直接结束请求,不是走下一个链。2
- 拒绝2019-09-04我们可以考虑在分布式锁前面新增一个等待队列,减缓抢购出现的集中式请求,相当于一个流量削峰。当请求的 key 值放入到队列中,请求线程进入阻塞状态,当线程从队列中获取到请求线程的 key 值时,就会唤醒请求线程获取购买资格。 老师这里不太理解!
作者回复: 相当于线程池中的阻塞队列
共 2 条评论2 - 梁中华2019-09-03我们上次把redis客户端从jedis改成redission后,会有部分查询请求出现延迟几十毫秒的现象,换回jedis里面好了,不知道老师有没有遇到过这种情况,是不是netty的很么参数设置的不对?
作者回复: 是的,可以参考下官方的使用文档,在单机且运用服务的CPU核数比较小的环境下,可能测试性能效果没有很大差别,如果想要效果更明显,可以在redis集群环境且应用服务的CPU核数在16以上的环境下进行性能压测,效果会更明显。 https://github.com/redisson/redisson/wiki/2.-配置方法#21-程序化配置方法
2 - Mr.Strive.Z.H.L2019-10-09老师你文中提到的 锁库存,我理解就是缓存中扣减库存,因为没有涉及到db,所以没有实际的上锁。是这样吧? 如果用户迟迟没付款,订单超时后会增加缓存的库存吗?
作者回复: 扣除缓存中的库存也需要分布式锁,订单超时被取消会增加库存。
1 - 晓杰2019-09-01问答题:在获取购买资格这一步,可以适当加大购买资格的数量
作者回复: 到了支付界面,我们已经锁定库存了,所以即使增大购买资格,也没法解决这个问题。
1 - 晓杰2019-09-01请问老师,在提交订单的时候加上订单的幂等校验是为了防止同一个用户重复提交订单吗
作者回复: 对的
1 - 许童童2019-08-31期待老师的思考题解答。
作者回复: 嗯,黑名单机制是一个方向
1 - really2022-10-18 来自广东把库存放到redis,redis不能保证数据不丢失,如果出现了主从切换,那会超卖的
- 书策稠浊2021-09-10提交订单前不是有一个获取资格的过程吗,有资格的用户数就那么多,所以口库存的时候流量其实不会很大。 比如只有1000库存,那就发2000个资格,只有2000个用户可以进入到提交订单的页面
- 平民人之助2021-07-11我是航司的架构,这种方案航司那边是有退票扣费的操作,避免买特价票了不坐。只能从业务上去限制,就像你打开门做生意,做不做都得让别人进来吧,进来不做的走导致有人买不到,那就不是技术问题了。