抢购的实现和分布式锁

1. 抢购功能的基本业务

public synchronized void qgGoods(String token, String goodsId) throws Exception {
        // 1.用户未登录无法进行抢购
        QgUserVO qgUser = rpcTokenService.getCurrUser(token);
        if(EmptyUtils.isEmpty(qgUser)){
            throw new Exception("用户还未登录!");
        }

        // 2.一个用户只能抢购一次
        boolean flag = rpcQgGoodsService.checkUserAlreadyQg(goodsId, qgUser.getId());
        if(flag){
            throw new Exception("用户已经抢购!请不要重复抢购!");
        }
        // 3.验证商品是否还有库存
        int currStock = rpcQgGoodsService.getCurrStock(goodsId);
        if(currStock <= 0){
            throw new Exception("对不起!商品已经售罄!请下次赶早!");
        }
        // 4.进行库存锁定
        rpcQgGoodsService.lockStock(goodsId, qgUser.getId());

2.优化

问题1:商品信息查询,每个用户进来都需要查询一次 这个过程就很慢

抢购的实现和分布式锁_第1张图片
服务器提升性能的方式有很多 主流的一种方式—>我们使用缓存
抢购的实现和分布式锁_第2张图片
抢购的实现和分布式锁_第3张图片

前端也可以优化:少发一些请求,例如图片如果基本不是变化的,后台把图片进行隔离,降低查询频率

判断用户是否已经抢购过
抢购的实现和分布式锁_第4张图片
库存锁定
抢购的实现和分布式锁_第5张图片
抢购的实现和分布式锁_第6张图片

问题2:在抢购方面的优化,高并发引发的问题—>1.线程不安全(当你多个请求来的时候,对同一个数据进行修改的操作,由于资源共享 , 10个来抢,结果抢出来11条记录);2.多线程情况下,是争抢模式进行的,并不是我们所想的第一个进来,就是第一个结束
  1. 以前解决线程不安全的问题,我们用synchronized,但是他只适用于单机。没有办法保证多个系统中jvm是同一个
    我们现在是分布式的场景下,就不好搞定------>采用分布式锁
  2. 有关顺序的问题 我们使用消息队列—消息中间件来解决
  3. 提升速度—消息中间件也可以帮我们解决 请求来了以后可以快速返回给客户端

2.1 分布式锁(锁 大概理解:请求过来的时候,第一个请求先进行处理,处理结束完以后再进行接着后续的请求)

分布式锁三种实现:

1.使用zookeeper 性能平均 实现平均
2.使用redis 性能比较好 实现比较简单
抢购的实现和分布式锁_第7张图片
3.数据库 性能是最差的 实现非常麻烦

本项目所采用分布式锁实现:

1.用什么操作redis? redis已经提供了jedis客户端用于java应用程序,直接调用jedis API即可。
2.怎么实现加锁?
“锁”其实是一个抽象的概念,将这个抽象概念变为具体的东西,
就是一个存储在redis里的key-value对,key是于商品ID相关的字符串来唯一标识,
value其实并不重要,因为只要这个唯一的key-value存在,就表示这个商品已经上锁。

	setnx key value 加锁

3.如何释放锁?
既然key-value对存在就表示上锁,那么释放锁就自然是在redis里删除key-value对。
del key 释放锁

4.阻塞还是非阻塞?
采用了阻塞式的实现,若线程发现已经上锁,会在[特定时间内]轮询锁。
5.如何处理异常情况?
比如一个线程把一个商品上了锁,但是由于各种原因,
没有完成操作(在上面的业务场景里就是没有将库存-1写入数据库),自然没有释放锁,
这个情况加入了锁超时机制,利用redis的expire命令为key设置超时时长,过了超时时间redis就会将这个key自动删除,
即强制释放锁(可以认为超时释放锁是一个异步操作,由redis完成,应用程序只需要根据系统特点设置超时时间即可)。

2.2 消息中间件

在这里插入图片描述
抢购的实现和分布式锁_第8张图片

抢购的实现和分布式锁_第9张图片
抢购的实现和分布式锁_第10张图片

主流的消息中间件
抢购的实现和分布式锁_第11张图片

你可能感兴趣的:(抢购的实现和分布式锁)