基于redis实现分布式锁

package com.dlss.loyalty.common.util;

import com.dlss.common.redis.RedisClientTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

import javax.annotation.Resource;
import java.util.List;
import java.util.UUID;


@Component
@Slf4j
public class RedisLock {

    private static final String PREFIX = "loyalty:lock:";

    @Resource
    private RedisClientUtil redisClientTemplate;

/*

lockName 锁名称

acquireTimeOut 等待时间

lockTimeout 过期时间

*/
    public String lock(String lockName, long acquireTimeout, long lockTimeout) {

        String identifier = UUID.randomUUID().toString();
        String lockKey = PREFIX + lockName;
        // 锁的过期时间
        int lockExpire = (int) (lockTimeout / 1000); //锁过期时间

        long end = System.currentTimeMillis() + acquireTimeout; //获取锁等待时间
        while (System.currentTimeMillis() < end) {
            //setnx 判断锁是否存在,不存在则添加锁并设置失效时间
            if (redisClientTemplate.setnx(lockKey, identifier) == 1) {
                redisClientTemplate.expire(lockKey, lockExpire);
                return identifier;
            }
            //ttl -1 锁存在,但已经失效,重新添加锁失效时间;-2 锁不存在
            if (redisClientTemplate.ttl(lockKey) == -1) {
                redisClientTemplate.expire(lockKey, lockExpire);
            }

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                log.error("获取分布式锁失败", e);
                return null;
            }
        }
        return null;
    }


    public boolean unlock(String lockName, String identifier){
        String lockKey = PREFIX + lockName;
        while (true) {
            Jedis shard = redisClientTemplate.getShard("0");
            shard.watch(lockKey);//监视key,事务执行之前这个key 被其他命令所改动,那么事务将被打断
            if(identifier.equals(redisClientTemplate.get(lockKey))){
                Transaction transaction = shard.multi();//标记事务
                transaction.del(lockKey);
                List<Object> exec = transaction.exec();//提交事务
                if(exec == null){
                    continue;
                }
                return true;
            }
            shard.unwatch();
            break;
        }
        return false;
    }
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值