07|强一致锁:如何解决高并发下的库存争抢问题?
该思维导图由 AI 生成,仅供参考
锁争抢的错误做法
- 深入了解
- 翻译
- 解释
- 总结
在高并发场景下,解决库存争抢问题是一个技术挑战。本文深入探讨了多种解决方案和优化方法。首先,通过并发库存锁的案例引出了多线程并行对同一变量读写可能出现的数据损坏问题,强调了使用锁或原子操作来保证变量在多线程并发情况下的准确性。随后,介绍了原子操作、将热门商品库存拆分放置在多个key中以及使用Redis的原子操作来保证库存的准确性。同时,指出了这些方法的局限性,如在处理业务故障时需要人工代码保障库存问题,以及在高并发情况下锁的自旋阻塞等待会浪费系统资源。此外,还讨论了多库存秒杀的设计调整和CAS乐观锁的实现方式。最后,介绍了使用Redis Lua脚本实现多步骤库存操作的方式。总的来说,本文通过具体案例和技术原理深入浅出地介绍了在高并发场景下解决库存争抢问题的方法和优化思路,对于需要解决类似问题的读者具有一定的参考价值。 文章通过具体案例和技术原理深入浅出地介绍了在高并发场景下解决库存争抢问题的方法和优化思路。从并发库存锁问题出发,介绍了原子操作、拆分热门商品库存、CAS乐观锁等多种解决方案,并指出了它们的局限性。最后,通过Redis Lua脚本实现多步骤库存操作的方式。文章内容丰富,对读者解决类似问题具有一定的参考价值。
《高并发系统实战课》,新⼈⾸单¥59
全部留言(17)
- 最新
- 精选
- Geek_8438e4面试原题,请指教:既然你们减库存用了redis,那如果redis挂了怎么办
作者回复: 你好,目前为止我了解到的情况是,首先数据层有故障基本都是有损的,只是数据多少的问题。如线上数据层出现故障很多基础服务是不会马上就切换的,因为redis以及类似的数据服务都会有个探测过程,以防止只是一时业务查询导致的卡顿导致误判,像redis使用keepalive或哨兵时,也是通过多次ping检测来判断服务是否真正失联,多次延迟确认后才会切换主从,但是这样过程探测过程会过去五分钟以上,所以这个问题严谨一些的说他想问你能做哪些措施预防服务损坏,而不是让我们去讲完美无缺的提供服务强一致,秒杀肯定是要保证库存不要出错的,所以故障了多副本保证切换后数据十分精准的要求是无法满足的,行业出现这个情况是立即停止秒杀活动或者 降级服务 然后将请求放入队列后做相应补救。另外redis mysql等如果对一致性要求高的话,需要做的代价就特别大,每次切换主后从库都是需要同步主库所有数据进度,想要做好这里需要有性能很好的两个从库一起同步数据。所以做好前期流量预测,做好压测,预备措施可以准备一些但是多少都会丢一点
2022-12-14归属地:内蒙古511 - 赵旭问题1:秒杀秒杀肯定是很快就没库存了,只要分片够均匀,在一个分片查不到就返回‘没有库存’或者‘参与用户太多,稍后再试‘呗,如果是要持续几分钟的才能抢完的,这种级别的流量一般也不用分片
作者回复: 你好,这确实是一个知识点
2022-12-07归属地:内蒙古5 - 移横为固问题1:库存拆开后,当某个库存key数量为0后,删除这个key,减少下次接口调用需要查询的key数量。 在不考虑库存场景下,用锁的性能最高的就是不要有锁,如netty的reactive模型,把操作对象与线程进行绑定,避免争抢;还有ThreadLocal的线程副本。库存场景是对共享资源的操作,感觉只能用锁来同步
作者回复: 你好,移横为固,这样如何保证不超卖呢?
2022-11-09归属地:北京2 - 张申傲这节课对于复习 Redis 很有帮助~
作者回复: 你好,申傲,有任何疑问~多多交流!
2022-11-08归属地:北京2 - 李喂马请教个问题,全文讲的都是扣减库存的安全性和性能,但是秒杀系统经常会面临一些爬虫,在活动开始瞬间大量的爬虫请求导致库存被扣减完毕(这些些请求都的ip都是经过伪装的),导致真实用户无法购买到商品,面对这种情况老师有没有一些好的解决方案~
作者回复: 你好,这里可以通过 js 对单次请求进行加密签名,并且保证每次秒杀接口入口流程和校验方式,每个活动都不同,这样能预防对方写一次脚本刷全站。 同时,这样做之后,他的爬虫必须使用我们的脚本计算才能正确请求,提高爬虫的门槛,因为这样对方就需要可编程浏览器才能模拟用户来抢,这个代价就会大很多。 另外要求必须真实绑定手机号用户才可以刷,限制单个用户指定时间内并发请求量,限制一个用户购买量,有未成交的不允许再下单,不用数字代表商品 id,让商品标识非数字连贯等多个组合。 总结一下就是不断提高技术要求和门槛,来降低他们抢的性价比。
2023-01-04归属地:北京41 - dumplingrpop 支持一次性移出多个元素吗?哪个版本支持的特性?
作者回复: 你好,dumpling,这里有点理解错误,rpop不支持多元素取出,原文:“改用 rpop 实现多个库存扣减。”是说使用rpop指令是解决方案中的一环主要特指令牌方式的实现方式,后续说解决多个库存是和他平级的环节。
2022-11-27归属地:北京31 - 阿昕思考题:1.库存为了0接口缓慢,主要是因为需要遍历不同的key,可以把为0的key标记为删除,减少遍历次数;
作者回复: 你好,如果是用incr这个方式,那么这里有个缺陷,服务端不知道这个key已经被删除了,他实际还是会decr一下这个操作~可能会出现负数
2023-04-06归属地:浙江 - Spoon1.拆分均匀地情况下,基本很快都被秒杀完,直接让用户重试就好 2.消除锁冲突,改成MQ顺序队列方案,其实有很多系统在进DB前都采用排队方式减少冲突
作者回复: 有一瞬间极端情况,这种情况平时没什么,高峰期极端情况会雪崩,锁冲突这个方式缺点是消费过慢,并发高的几秒可能需要三小时消费完所有队列堆积
2023-03-28归属地:浙江6 - 花轮君针对于分片库存为0的场景,可以设定分片库存是否执行的标记,实时:当分片库存为0时原子化变更分片库存标记,定时:定时check 分片库存标记
作者回复: 你好,这个方式缺点是退货后延迟一会儿才能拿到,好处是减少了不必要的尝试,是否合理要看我们业务需要
2023-03-21归属地:上海 - 普通熊猫 ଘ(੭ˊ꒳ˋ)੭✧1. 我不认为基于redis锁的方案是一个好的秒杀方案, redis是一个AP系统, redis的分布式锁用于限流是可以的, 用于库存就有些危险了. 2. 如果让我设计的话, 主要做两点就够了. 一是限流: 基于总数的 (放10倍, 100倍于库存的流量进来都可以), 基于ip的, 基于user id的, 各种限流. 二是把下单请求放MQ中. 3. 放到MQ中的请求, 后面只需要架2台微服务慢慢消费就可以了, 后面所有扣减库存的操作都直接在DB里基于事务进行. 不需要架设大量的微服务, 因此也不需要考虑太多DB写压力的问题.
作者回复: 你好,各有千秋,是否适合取决于业务规模:)
2023-03-10归属地:北京3