spring boot学习第十九篇:使用redission模拟抢单,分析验证高并发情况分布式锁的作用

1、引入依赖

<dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>${redisson.version}</version>
        </dependency>
<redisson.version>2.15.2</redisson.version>

2、编写接口类

package com.hmblogs.backend.controller;

import com.hmblogs.backend.dao.StockMapper;
import com.hmblogs.backend.entity.Stock;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

@RestController
@Slf4j
public class OrderRedissionController {

    @Autowired
    private StockMapper stockMapper;

    @Autowired
    private RedissonClient redissonClient;

    //商品key名字
    private String shangpingKey = "computer_key";
    //获取锁的超时时间 秒

    /**
     * 该接口逻辑中已模拟并发,调用该接口不用做压测也行。
     * @return
     */
    @GetMapping("/redission/qiangdan")
    public List<String> qiangdan() {
        //抢到商品的用户
        List<String> shopUsers = new ArrayList<>();
        //构造很多用户
        List<String> users = new ArrayList<>();
        for(int i=0;i<16;i++) {
            users.add("神牛-" + i);
        }
        //模拟开抢
        users.parallelStream().forEach(user -> {
            String shopUser = qiang(user);
            if (!StringUtils.isEmpty(shopUser)) {
                shopUsers.add(shopUser);
            }
        });
        return shopUsers;
    }

    /**
     * 模拟抢单动作
     *
     * @param user
     * @return
     */
    private String qiang(String user) {
        RLock rLock = redissonClient.getLock(shangpingKey);
        rLock.lock(60, TimeUnit.SECONDS);
        //用户b拿到锁
        log.info("用户{}拿到锁...", user);
        try {
            int id = 1111;
            Stock stock = new Stock();
            stock.setId(id);
            Stock stockDo = stockMapper.findById(stock);
            Integer quantity = stockDo.getQuantity();
            if(quantity!=null && quantity>0){
                stockMapper.updateStockById(stock);
                log.info("update success.");
            }else{
                log.info("no update.");
            }
        } finally {
            log.info("用户{}释放锁...", user);
            //释放锁
            rLock.unlock();
        }
        return user;
    }


    /**
     * 调用该接口需要做压测
     */
    @GetMapping("/redission/qiangdan22")
    public void qiangdan22() {
        RLock rLock = redissonClient.getLock(shangpingKey);
        rLock.lock(60, TimeUnit.SECONDS);
        //用户b拿到锁
        log.info("用户拿到锁...");
        try {
            int id = 1111;
            Stock stock = new Stock();
            stock.setId(id);
            Stock stockDo = stockMapper.findById(stock);
            Integer quantity = stockDo.getQuantity();
            if(quantity!=null && quantity>0){
                stockMapper.updateStockById(stock);// 库存减1
                log.info("update success.");
            }else{
                log.info("no update.");
            }
        } finally {
            log.info("用户释放锁...");
            //释放锁
            rLock.unlock();
        }
    }
}

3、验证这2个接口,库存最后都是0,而不是负数。

3.1、验证第1个接口

3.2、验证第2个接口,要做压测。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值