1572662

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 

1、  pom.xml中引入相关依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-redis</artifactId>
        <version>2.2.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.8.1</version>
    </dependency>
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>20.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>5.1.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

 

 

2、  定义获取redis锁和释放redis锁方法的工具类

package com.example.java8test;

import com.google.common.base.Throwables;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component
@Slf4j
public class RedisUtils {
    @Resource
    private RedisTemplate<String,Object> redisTemplate;

    /**
     *
获取redis
    
* @param key
    
* @param value 当前时间 + 超时时间
    
* @return 是否成功获得锁
    
*/
   
public boolean lock(String key,String value){
        Boolean success = redisTemplate.opsForValue().setIfAbsent(key,value);
        if(null != success && success){
            return true;
        }
        String currentValue = (String) redisTemplate.opsForValue().get(key);
        //如果当前值不为空,且值小于系统时间,说明锁已过期(过期的锁由于某种原因未被删除)
       
if(!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()){
            //当两个线程都满足上边的条件,进入该if语句,需要只有一个线程能够获得锁成功返回true,另一个返回false,
            //
所以需要用再次获取到的值与最开始的原值进行比较,相同才说明获得锁成功
           
String oldValue = (String) redisTemplate.opsForValue().getAndSet(key,value);
            return StringUtils.isNotEmpty(oldValue) && oldValue.equals(currentValue);
        }
        return false;
    }


    public void unlock(String key,String value){
        try {
            String currentValue = (String)redisTemplate.opsForValue().get(key);
            if(!StringUtils.isEmpty(currentValue) && currentValue.equals(value)){
                redisTemplate.opsForValue().getOperations().delete(key);
            }
        } catch (Exception e) {
            log.error("redis unlock exception: {}", Throwables.getStackTraceAsString(e));
        }
    }

}

 

 

3、  在程序中使用redis锁

package com.example.java8test;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/example")
@RestController
@Slf4j
public class ExampleController {
    private static final  String key = "example:redis:test:";
    @Autowired
    private RedisUtils redisUtils;

    @PostMapping("/saveRecord")
    public String saveRecord(String recordId){
        //仅是为了演示如何使用redis
       
long time = System.currentTimeMillis();
        boolean lock = redisUtils.lock(key + recordId,String.valueOf(time + 10 * 1000));
        if(!lock){
            return "fail";
        }
        try {
            log.info("进行保存记录的相关操作");
            return "success";
        } catch (Exception e) {
            log.error("saveRecord failed: {}",e);
            return "fail";
        } finally {
            redisUtils.unlock(key + recordId,String.valueOf(time + 10 * 1000));
        }

    }

}

 

posted on 2020-06-28 10:01  1572662  阅读(204)  评论(0)    收藏  举报