redis分布式锁

加入redis依赖和配置

	<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>

在这里插入图片描述

两个关键的方法

//只有在 key不存在时设置 key 的值   之前已经存在返回false,不存在返回true
redisTemplate.opsForValue().setIfAbsent(key, value)
//getAndSet 将给定 key的值设为 value ,并返回 key 的旧值(old value)
String oldValue = redisTemplate.opsForValue().getAndSet(key, value);
//删除key
redisTemplate.opsForValue().getOperations().delete(key)

实现redis分布式锁

package com.imooc.service;

/**
 * @author LB
 * @Remarks
 * @date 2020/01/07 22:08
 */
@Component
@Slf4j
public class RedisLock {

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     *加锁
     * @param key
     * @param value 当前时间+超时时间
     * @return
     */
    public boolean lock(String key,String value){
        //只有在 key不存在时设置 key 的值   之前已经存在返回false,不存在返回true
        if(redisTemplate.opsForValue().setIfAbsent(key, value)) {
            //设置 key 的值 成功
            return true;
        }
        
        //---防止(获取锁后业务代码报错造成没有解锁)死锁开始
        String currentValue = redisTemplate.opsForValue().get(key);
        //如果锁过期
        //!StringUtils.isEmpty(currentValue)   内容不为空
        //Long.parseLong(currentValue) < System.currentTimeMillis()  小于当前时间
        if (!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()) {
            //获取上一个锁的时间
            //getAndSet 将给定 key的值设为 value ,并返回 key 的旧值(old value)
            String oldValue = redisTemplate.opsForValue().getAndSet(key, value);
            //oldValue 不为空并和当前的value相等
            if (!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)) {
                return true;
            }
        }
        //---防止死锁结束
        return false;
    }


    /**
     * 解锁
     * @param key
     * @param value
     */
    public void unlock(String key, String value) {
        try {
            String currentValue = redisTemplate.opsForValue().get(key);
            if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {
                redisTemplate.opsForValue().getOperations().delete(key);
            }
        }catch (Exception e) {
            log.error("【redis分布式锁】解锁异常, {}", e);
        }
    }
}

业务代码

 @Override
    public void orderProductMockDiffUser(String productId)
    {
        //加锁
        long time = System.currentTimeMillis()+TIMEOUT;
        if(!redisLock.lock(productId,String.valueOf(time))){
            throw new SellException(101,"抢的人太多了,换个姿势试试");
        }
        //1.查询该商品库存,为0则活动结束。
        int stockNum = stock.get(productId);
        if(stockNum == 0) {
            throw new SellException(100,"活动结束");
        }else {
            //2.下单(模拟不同用户openid不同)
            orders.put(KeyUtil.genUniqueKey(),productId);
            //3.减库存
            stockNum =stockNum-1;
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            stock.put(productId,stockNum);
        }
        //解锁
        redisLock.unlock(productId,String.valueOf(time));
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值