redis锁 工具类

基于 org.springframework.data.redis.core.RedisOperations做的一个REDIS-SETNX分布式锁。

 

/*
 * Copyright (c) 2019. 唐江华 保留所有权。
 */



import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisOperations;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * @author tangjianghua
 * date 2020/4/8
 * time 9:58
 */
public class RedisLock implements Lock {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private String key;

    private final String value = "LOCK";

    private RedisOperations redisOperations;

    /**
     * 尝试获取锁的间隔 1s
     */
    private final long INTERVAL = 1000L;

    /**
     * 获取锁的最大尝试次数
     */
    private final int MAXTRY = 10;

    /**
     * 获取锁状态
     * true:获取到锁
     * false: 为获取到锁
     */
    private boolean lock = false;

    /**
     * 默认超时时间 10分钟
     */
    private final long DEFAILT_EXPIRE = 10L;

    /**
     * 默认超时单位
     */
    private final TimeUnit DEFAILT_UNIT = TimeUnit.MILLISECONDS;

    public RedisLock(RedisOperations redisOperations,String key) {
        this.key = key;
        this.redisOperations =redisOperations;
    }

    @Override
    public void lock() {
        this.lock = redisOperations.opsForValue().setIfAbsent(key, value);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
      //TODO
    }

    @Override
    public boolean tryLock() {
        int i = 0;
        do{
            logger.info("线程"+Thread.currentThread().getId()+"--第"+i+"次尝试获取锁--"+key);
            lock();
            if(!lock){
                try {
                    Thread.sleep(INTERVAL);
                    i++;
                    continue;
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }else {
                logger.info("线程"+Thread.currentThread().getId()+"--获取到锁--"+key);
                break;
            }
        }while (i < MAXTRY);
        return lock;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit){
        if(time == 0L){
            time = DEFAILT_EXPIRE;
        }
        if(unit == null){
            unit = DEFAILT_UNIT;
        }
        if(!tryLock()){
            return false;
        }
        Boolean aBoolean = redisOperations.expire(key, time, unit);
        if(!aBoolean){
            unlock();
        }
        logger.info("线程"+Thread.currentThread().getId()+"--为锁添加超时--"+key+"--"+time+"--"+unit.name());
        return aBoolean;
    }


    /**
     * 默认超时获取锁
     * @return
     */
    public boolean tryLockDefaultExpire(){
        return  tryLock(0L, null);
    }

    @Override
    public void unlock() {
        if(!lock){
            logger.info("线程"+Thread.currentThread().getId()+"--未获取到锁,无需释放--"+key);
          return;
        }
        redisOperations.delete(key);
        this.lock = false;
        logger.info("线程"+Thread.currentThread().getId()+"--释放锁--"+key);
    }

    /**
     * 是否拥有锁
     * @return
     */
    public boolean isLock(){
        return lock;
    }

    @Override
    public Condition newCondition() {
        return null;
    }
}

 

您好!对于高性能的 Redis 工具类,可以考虑以下几个方面进行设计和实现: 1. 使用 Redis 的原子操作:Redis 提供了多个原子操作指令,如 SETNX(set if not exists)和 EXPIRE(设置过期时间),可以用来实现分布式。可以使用 SETNX 指令尝试获取,如果获取成功则设置过期时间,并在释放时使用 DEL 指令删除。 2. 考虑的可重入性:在分布式环境下,同一个线程可能多次请求同一个。为了保证可重入性,可以在的数据结构中增加一个计数器,每次获取时将计数器加一,释放时将计数器减一,只有计数器归零才真正释放。 3. 考虑的可靠性:由于网络等原因,可能存在获取成功但无法设置过期时间的情况。为了避免这种情况导致死,可以使用 Lua 脚本将 SETNX 和 EXPIRE 操作合并为一个原子操作。 4. 考虑的超时机制:为了避免被长时间持有而导致其它线程无法获取,可以为设置一个超时时间。在获取时可以记录当前时间戳,并在释放时检查是否已超过超时时间,如果超时则自动释放。 5. 考虑的释放机制:为了保证的正常释放,可以使用 try-finally 或者 try-with-resources 等机制,在代码块结束时自动释放。 综上所述,您可以基于上述思路设计一个高性能的 Redis 工具类,满足分布式环境下的并发控制需求。希望对您有所帮助!如有更多问题,请继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值