30 | 生产者消费者模式:电商库存设计优化
该思维导图由 AI 生成,仅供参考
Object 的 wait/notify/notifyAll 实现生产者消费者
Lock 中 Condition 的 await/signal/signalAll 实现生产者消费者
- 深入了解
- 翻译
- 解释
- 总结
生产者消费者模式在电商库存设计中的优化应用是本文的重点。文章首先介绍了两种实现方式:使用Object的wait/notify/notifyAll和Lock中Condition的await/signal/signalAll,并分析了它们的优缺点。随后通过代码案例展示了如何使用Lock和Condition来优化生产者消费者模式,将生产者和消费者的等待条件和锁资源分离,以提高系统并发性能。另外,文章还介绍了使用BlockingQueue实现生产者消费者模式的简单明了方式,并通过案例展示了如何使用LinkedBlockingQueue来实现生产者消费者模式。通过对比不同实现方式的优缺点和代码案例展示的优化方法,读者可以快速了解生产者消费者模式在电商库存设计中的应用及优化方法。此外,文章还提到了生产者消费者模式在缓冲高并发数据库扣除库存压力和处理执行任务时间较长的场景中的应用,以及思考题引发了读者对线程阻塞性能问题的思考。整体而言,本文通过详细的技术讲解和案例分析,为读者提供了深入了解生产者消费者模式在电商库存设计中的应用及优化方法的机会。
《Java 性能调优实战》,新⼈⾸单¥59
全部留言(34)
- 最新
- 精选
- Jxin1.生产消费模式用信号量也能玩。 2.生产者这边的优化思路应该是提高响应速度和增加资源。提高响应速度就是尽量降低生产逻辑的耗时,增加资源就是根据业务量为该生产者单独线程池并调整线程数。至于限流和令牌桶感觉都是降级处理,属于规避阻塞场景而非解决阻塞场景,应该不在答案范围内吧。 3.对于进程内生产消费模式,大规模,量大的数据本身就不适合,毕竟内存空间有限,消息堆积有限,所以量级达到一定指标就采用跨进程方式,比如kafka和rocketmq。同时,进程内生产消费模式,异常要处理好,不然可能会出现消息堆积和脏数据,毕竟mq的消费确认和重试机制都是开箱即用,而我们得自己实现和把关。
作者回复: 看来有实战经验👍🏻
2019-07-31327 - 杨俊我的理解是库存放缓存,用户提交订单在缓存扣减库存,用户端能够快速返回显示订单提交成功并支付,然后只有支付成功之后才会利用队列实际的扣减数据库库存是吗?要是不支付会在缓存补回库存吧,应该会限时支付吧
作者回复: 对的
2019-07-30218 - QQ怪在网关层中把请求放入到mq中,后端服务从消费队列中消费消息并处理;或者用有固定容量的消费队列的令牌桶,令牌发生器预估预计的处理能力,匀速生产放入令牌队列中,满了直接丢弃,网关收到请求之后消费一个令牌,获得令牌的请求才能进行后端秒杀请求,反之直接返回秒杀失败
作者回复: 大家都一致想到了限流,限流是非常必要的,无论我们的程序优化的如何,还是有上限的,限流则是一种兜底策略。 除了这个,我们还可以使用协程来优化线程由于阻塞等待带来的上下文切换性能问题,可以回顾第19讲,我们也用协程实现过生产者消费者模式。
2019-07-3059 - JasonK你好,刘老师,最近生产上一个服务,老是半夜cpu飙升,导致服务死掉,排查问题看了下,都是GC task thread#15 (ParallelGC) 线程占用CPU资源,这是为什么?而且同样的服务我布了两台机器,一台服务会死掉,一台不会。请老师解惑。
作者回复: 导致CPU飙升只是一个性能的直接表现,是不是有对象一直在创建,所以导致一直在GC。建议打开dump日志查看具体的内存使用情况以及对象的创建分布情况。
2019-07-3133 - 明翼老师,生产者和消费者的锁分开没问题吗?都是用的同一个队列?
作者回复: 这里同步更新下,新增了以下代码作为实时库存: private AtomicInteger inventory = new AtomicInteger(0); 我们这里是基于LinkedList来存取库存的,虽然LinkedList是非线程安全,但我们新增是操作头部,而消费则是操作队列的尾部,理论上来说没有线程安全问题。而库存的实际数量inventory是基于AtomicInteger(CAS锁)线程安全类实现,即可以保证原子性,也可以保证消费者和生产者之间是可见的。
2019-07-3023 - 罗洲生产方的高并发优化,我们可以参考下tomcat的设计,tomcat设计了线程池来进行请求接收,有最小线程数,最大线程数,同时还有一个有界的工作队列,来接收超过线程数的请求,当工作队列满了后可以选择拒绝或者丢弃处理。
作者回复: 赞,很好的参考例子
2019-07-3023 - 撒旦的堕落网关与服务之间增加令牌桶 或者mq 以保护秒杀服务不会被大的流量压垮 可以么
作者回复: 可以的,很通用的一种解决方案
2019-07-302 - 2102增加消费者
作者回复: 增加消费者是一种方式
2019-10-191 - 怎☞劰☜叻老师,我看到你上面说用协程来优化!我们这边有个服务属于业务网关,要聚合多个下有的数据,涉及大量的网络io,之前是使用多线程并行调用多个下有,现在发现线程越来越多,遇到了瓶颈!希望用协程来改进方案~但是我在网上找到的一些java协程开源组件,文档和生态都不是很健全,希望老师能给出一些建议~ 非常感谢
作者回复: 建议再等等官方的协成组件,或改用go实现,目前Java的一些第三方开源组件的生产环境的实践以及性能验证有待考验,如果不介意当小白鼠,也可以试试这些第三方协成组件。
2019-08-091 - 一个卖火柴的老男人商品从数据库压入redis 缓存。 同时库存压入redis,用商品ID作为key,用list模拟队列【1001,1001,1001】用商品🆔做队列元素,100件库存,那就存100个🆔在队列中,扣库存的时候,判断队列大小,可以防止超卖。所有都是靠redis的单线程原子操作保证,可行不
作者回复: 可行
2019-08-0321