springboot redisson分布式锁

1.添加依赖

   <!--springboot startWeb -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <version>2.1.6.RELEASE</version>
            </dependency>
           <!-- redis-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
                <version>2.2.6.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-pool2</artifactId>
                <version>2.6.2</version>
            </dependency>
            <!-- redisson -->
            <dependency>
                <groupId>org.redisson</groupId>
                <artifactId>redisson</artifactId>
                <version>3.12.3</version>
            </dependency>

2.配置属性

spring:
  redis:
    host: 127.0.0.1
    port: 8999
    database: 1
    password: 12356

 

3.编写RedissonConfig

/**
*@ClassName RedissonConfig
*@Description Redisson框架集成
*@Author 
*@Date 
*@Time 
*@Version v1.0
*/
@Configuration
public class RedissonConfig {

    @Value("${spring.redis.host}")
    private String redisServerIp;

    @Value("${spring.redis.port}")
    private String redisServerPort;

    @Value("${spring.redis.password}")
    private String redisPassword;

    @Bean
    Config getConfig(){
        Config config = new Config();
        String address = "redis://"+redisServerIp+":"+redisServerPort;
        //单节点模式,更多模式见官方文档 https://github.com/redisson/redisson/wiki
        config.useSingleServer().setAddress(address).setPassword(redisPassword);
        return config;
    }

    @Bean
    RedissonClient getRedisClient(Config config){
        RedissonClient redissonClient = Redisson.create(config);
        return redissonClient;
    }

}

4.使用redisson加锁 防止连续点击

 @Autowired
    RedissonClient redissonClient;

//防止重复点击
        RLock fairLock = redissonClient.getLock(PuhuiyunRedisKeyConstants.PUHUIYUN_SAVE_USERADDRESS_LOCK + userId);
        try {
            if (!fairLock.tryLock(0, 60, TimeUnit.SECONDS)) {
                return ApiRes.getErrorInstance(ResultEnum.REQUEST_LIMIT_ERROR);
            }
            return puhuiyunUserAddressService.savePuhuiyunUserAddress(id,userId,userName,userMoblie,userAddress);
        }catch (Exception e){
            log.error("保存/编辑 收货地址错误",e);
        } finally {
            if (fairLock.isHeldByCurrentThread() && fairLock.isLocked()) {
                //判断是当前线程加的锁就释放 并且 锁未释放
                fairLock.unlock();
            }
        }

5.封装一个Redis分布式锁工具类

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

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

/**
 * @author 
 * @title: RedisLok
 * @description: Redis分布式锁工具类
 * @date 
 */
@Component
@Slf4j
public class RedisLok {

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 枷锁 自定义秒
     *
     * @param key
     * @param value
     * @return
     */
    public boolean tryLock(String key, String value, Long timeout) {

        return tryLockPackage(key, value, timeout);
    }

    /**
     * 枷锁 默认60秒
     *
     * @param key
     * @param value
     * @return
     */
    public boolean tryLock(String key, String value) {
        return tryLockPackage(key, value, 60L);
    }

    private boolean tryLockPackage(String key, String value, Long timeout) {
        DefaultRedisScript<Long> defaultRedisScript = new DefaultRedisScript<>();
        defaultRedisScript.setResultType(Long.class);
        defaultRedisScript.setScriptText("if redis.call('get',KEYS[1]) then return 1 else redis.call('set',KEYS[1],ARGV[1],'ex',ARGV[2],'NX') return 0 end");
        List<String> keys = new ArrayList<>();
        keys.add(key);
        Long result = redisTemplate.execute(defaultRedisScript, keys, value, String.valueOf(timeout));
        log.info("key:{} value:{} 失效时间:{} 脚本返回结果为:{}", key, value, timeout, result.intValue());
        return result.equals(0L);
    }

    /**
     * 封装执行 Lua脚本方法
     * @param luaScript 要执行的 lua 脚本
     * @param resultType 返回类型
     * @param keys key集合
     * @param argv arg集合
     * @param <T> 返回泛型
     * @return 泛型返回
     */
    public <T> T executeRedisLuaScript(String luaScript,Class<T> resultType,List<String> keys, List<?> argv){
        DefaultRedisScript<T> defaultRedisScript = new DefaultRedisScript<>();
        defaultRedisScript.setResultType(resultType);
        defaultRedisScript.setScriptText(luaScript);
        T execute = redisTemplate.execute(defaultRedisScript, keys, argv.toArray());
        log.info("执行Lua脚本,KEYS:[ {} ],ARGV:[ {} ]返回结果:{}", JSONObject.toJSONString(keys),JSONObject.toJSONString(argv),execute);
        return execute;
    }

    /**
     * 解锁
     *
     * @param key
     */
    public void unLock(String key) {
        log.info("删除的key为:{}", key);
        redisTemplate.delete(key);
    }
//------------------------------------redisson  相关操作-----------------------

    /**
     * redisson 解锁
     *
     * @param lock
     */
    public void redissonUnLock(RLock lock) {
        if (lock.isHeldByCurrentThread() && lock.isLocked()) {
            lock.unlock();
        }
    }

    public boolean tryRedissonLock(RLock lock) {
        return tryRedissonLock(lock, 0, 60, TimeUnit.SECONDS);
    }

    public boolean tryRedissonLock(RLock lock, long waitTime, long leaseTime, TimeUnit unit) {
        try {
            return lock.tryLock(waitTime, leaseTime, unit);
        } catch (InterruptedException e) {
            log.error("获取锁:{}失败", lock.getName(), e);
            return false;
        }
    }

    public boolean tryWaitTimeRedissonLock(RLock lock, long waitTime, TimeUnit unit) {
        return tryRedissonLock(lock, waitTime, 60, unit);
    }

    public boolean tryLeaseTimeRedissonLock(RLock lock, long leaseTime, TimeUnit unit) {
        return tryRedissonLock(lock, 0, leaseTime, unit);
    }


}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值