实现分布式锁

1.setnx+过期时间实现

public void testLock() {
    //从redis里面获取数据
    String uuid = UUID.randomUUID().toString();
    //1 获取当前锁  setnx  + 设置过期时间
    //        Boolean ifAbsent = redisTemplate.opsForValue().setIfAbsent("lock", "lock");
    Boolean ifAbsent =
            redisTemplate.opsForValue()
                    .setIfAbsent("lock", uuid,3, TimeUnit.SECONDS);

    //2 如果获取到锁,从redis获取数据 数据+1 放回redis里面
    if(ifAbsent) {
        //获取锁成功,执行业务代码
        //1.先从redis中通过key num获取值  key提前手动设置 num 初始值:0
        String value = redisTemplate.opsForValue().get("num");
        //2.如果值为空则非法直接返回即可
        if (StringUtils.isBlank(value)) {
            return;
        }
        //3.对num值进行自增加一
        int num = Integer.parseInt(value);
        redisTemplate.opsForValue().set("num", String.valueOf(++num));

        //3 释放锁 lua脚本实现
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        //lua脚本
        String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
                "then\n" +
                "    return redis.call(\"del\",KEYS[1])\n" +
                "else\n" +
                "    return 0\n" +
                "end";
        redisScript.setScriptText(script);
        //设置返回结果
        redisScript.setResultType(Long.class);
        redisTemplate.execute(redisScript, Arrays.asList("lock"),uuid);
        
    } else {
        try {
            Thread.sleep(100);
            this.testLock();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

2.Redisson

1.引入依赖
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
</dependency>
2 .创建Redisson配置类
@Data
@Configuration
@ConfigurationProperties(prefix = "spring.data.redis")
public class RedissonConfig {

    private String host;

    private String password;

    private String port;

    private int timeout = 3000;
    private static String ADDRESS_PREFIX = "redis://";

    /**
     * 自动装配
     *
     */
    @Bean
    RedissonClient redissonSingle() {
        Config config = new Config();

        if(!StringUtils.hasText(host)){
            throw new RuntimeException("host is  empty");
        }
        SingleServerConfig serverConfig = config.useSingleServer()
                .setAddress(ADDRESS_PREFIX + this.host + ":" + port)
                .setTimeout(this.timeout);
        if(StringUtils.hasText(this.password)) {
            serverConfig.setPassword(this.password);
        }
        return Redisson.create(config);
    }
}
 3.在业务方法编写加锁和解锁
@Autowired
private RedissonClient redissonClient;

//Redisson实现
@Override
public void testLock()  {
    
    //1 通过redisson创建锁对象
    RLock lock = redissonClient.getLock("lock1");

    //2 尝试获取锁
    //(1) 阻塞一直等待直到获取到,获取锁之后,默认过期时间30s
    lock.lock();
    
    //(2) 获取到锁,锁过期时间10s
   // lock.lock(10,TimeUnit.SECONDS);
    
    //(3) 第一个参数获取锁等待时间
    //    第二个参数获取到锁,锁过期时间
    //        try {
    //            // true
    //            boolean tryLock = lock.tryLock(30, 10, TimeUnit.SECONDS);
    //        } catch (InterruptedException e) {
    //            throw new RuntimeException(e);
    //        }

    //3 编写业务代码
    //1.先从redis中通过key num获取值  key提前手动设置 num 初始值:0
    String value = redisTemplate.opsForValue().get("num");
    //2.如果值为空则非法直接返回即可
    if (StringUtils.isBlank(value)) {
        return;
    }
    //3.对num值进行自增加一
    int num = Integer.parseInt(value);
    redisTemplate.opsForValue().set("num", String.valueOf(++num));
        
    //4 释放锁
    lock.unlock();
}

  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值