秒杀系统04-订单详情(分布式锁)

还是老三步,请求先到controller,controller找对对应方法,调用方法返回结果

秒杀系统04-订单详情(分布式锁)

 

秒杀系统04-订单详情(分布式锁)

 

秒杀系统04-订单详情(分布式锁)

 

 

但是现在还有问题,假如商品只有10件,但是来了1000个订单,那么会就失效,为了处理这个问题,所以引入了分布式锁。假如没有分布式锁,这里就会产生超卖问题。

超卖问题的原因在这儿:

秒杀系统04-订单详情(分布式锁)

第一步判断是否已经抢购,一般没有,能进入,第二部,判断是否可以被秒杀,这里就有问题了,假如1000个线程同时到达这里,都能判断能够秒杀,就多执行秒杀操作,这样就会造成超卖了 。原因就在于真正插入扣减成功的那段代码的逻辑晚于前面的判断。因为commonRecoedKillSuccessInfo方法就是为了后面再次线程再次调用killItem方法时就行判断,但是假如是并发进来了,那么很有可能这个判断方法还没执行

 

所以接下来采取分布式锁解决

 

协助方案:1.对于瞬时流量,并发请求进行限流(目的是接口的限流)

                      2.对服务做集群部署,提高高可用和稳定性

                      3.数据库mysql做主备部署,主从复制,读写分离

 

 

这里开始进行优化,首先是mysql层面的优化。

秒杀系统04-订单详情(分布式锁)

区别就是and total > 0,也就是sql语句多了一个条件,这样先保证库存是有效的,也就是不会出现负数。虽然数据库库存层面的问题解决了,但是插入订单消息数据那里却不能保证一人只能抢购一次,因为那里也是并发访问的,所以可能会一个人同时发多个请求,而这里明显是多个请求都生效了

 

为了解决上面的多一个人多次秒杀同一个商品的问题,所以开始使用分布式锁来进行优化。

redis分布式锁的使用:setnx+expire的使用

加入相关依赖,并且加入相关配置:

秒杀系统04-订单详情(分布式锁)

秒杀系统04-订单详情(分布式锁)

 

还有redis的配置类,在里面为redis配置序列化策略,redis连接工厂,序列化策略选择jackson2Json策略。然后配置stringredisTemplate。

秒杀系统04-订单详情(分布式锁)

 

分布式锁实现的秒杀商品

秒杀系统04-订单详情(分布式锁)

原理就是redis分布式锁的setnx。同一时间只能加入同一个key,插入成功的获取锁,使用释放锁,也就是删除该key,使得其他线程可以获取锁,这里就是基于的redis的setnx的原子操作来实现的分布式锁,最后删除锁(stringRedisTemplate,delete(key)),不过上面那样也有可能产生锁死的问题。也就是在使用这个锁之前出现了宕机,那么后面设置expire执行不了,删除锁也删除不了,所以就会永远不能执行。那么怎么办呢?可以进行集群部署,挂掉一个因为还有其他节点在,所以依然能够执行,不过还有更好的方法,也就是redis的内存淘汰策略。这里我们使用redisson来优化

导入redisson依赖:

秒杀系统04-订单详情(分布式锁)

秒杀系统04-订单详情(分布式锁)

 这里用的是单机模式,没有进行集群

具体方法:

秒杀系统04-订单详情(分布式锁)

redisson避免死锁的方法就是内部提供了一个监控锁的看门狗,它的作用是在redisson实例关闭前,不断的延长锁的有效期,默认情况是30s ,当实例关闭后,会自动进行释放锁的操作

 

redisson的优点:

提供的功能不仅包含了redis所提供,还提供了延迟队列,分布式服务,多种分布式对象

很多组件基于javase来提供服务,面向redis实现

秒杀系统04-订单详情(分布式锁)秒杀系统04-订单详情(分布式锁) qq_40058686 发布了137 篇原创文章 · 获赞 0 · 访问量 3831 私信 关注
上一篇:【springboot】使用redisson分布式锁


下一篇:在项目中,如何保证幂等性