深圳的某个办公室内,一枚长相帅气的程序员正在努力的搬砖。老板火急火燎的走到跟前对我说:“最近我们接到了一大批用户反馈说下完单后没有及时发货,已经有很多用户投诉了,你赶快去处理一下 ” 我急忙点头说好。然后开始检查订单数据,通过数据发现库存系统中某些商品的剩余数量竟然是负数,所以才导致无法发货(废话,库存都没有了还怎么发货。。),于是我把代码上上下下左左右右检查了几遍,竟然没发现任何问题,然后又不信邪的在测试环境试了几遍,还是没有发现。。。这个时候我的心里大概是这个样子的
正在我头痛欲裂、怀疑人生时,碰到了运维老哥,运维老哥告诉我,最近系统更改了的部署方案,由之前的单节点部署方案变成了分布式集群部署方案。
噢噢噢!原来如此,我想我知道问题所在了。
单节点部署方案
用户下单流程
- 用户发起下单请求
- 查询库存是否充足
- 库存充足则生成订单并扣减库存
(此处存在分布式事务的问题,本文不予讨论) - 响应用户下单成功或失败
单节点部署在并发量很小的时候还是挺正常的,整个流程的响应速度也算乐观,但是订单系统或库存系统其中任意一台服务down掉,都会中断整个业务流程。(耦合度过高,存在单点故障)。
因此才决定要改用分布式集群部署方案解决单点故障,提高系统可用性。
系统耦合性的问题可以通过中间件处理,本文不予讨论。
需要注意的是,这里的库存系统需要通过synchronized来控制并发操作的,否则此方案依然会出现线程安全问题
分布式集群部署方案
改用分布式集群部署方案后的流程图如上所示,看起来只是将订单系统与库存系统多部署了几个节点而已,但是这样在整个业务流程上却有所不同,首先我们先来分析一下此方案为什么会出现线程安全问题。场景如下
- 小何、小黄同时向订单系统进行下单,由于订单系统的负载均衡策略,将小何的请求交给了订单系统1去处理,小黄的请求交给了订单系统2去处理
- 订单系统1查询了库存系统1,发现库存充足
- 订单系统2查询了库存系统2,发现库存充足
- 订单系统1、订单系统2都发现库存充足,于是分别通知库存系统1、库存系统2进行扣减库存,这就导致了库存系统中商品数量被扣减为负数的情况,也叫做库存超卖现象。
出现这个问题的根本原因是分布式集群节点之间无法共享synchronized锁。既然问题已经分析出来了,那么解决问题方案自然就呼之欲出了。我们可以使用一把能够跨应用共享的分布式锁,锁住扣减库存的过程,这样一来在订单系统扣减库存的过程中,就不允许有其他的订单系统执行相同的操作。这样就可以保证了分布式集群环境下的线程安全性问题。
for(int i=0;i<3;i++){
System.out.print("重要的事情说三遍:求点赞、求关注、求分享!!!");
}
!