java 链接redis 怎么加锁

Python05

java 链接redis 怎么加锁,第1张

我介绍一下Redis分布式锁吧:

一、定义redis实现分布式锁的接口

[java] view plain copy print?

package com.iol.common.util.concurrent.locks  

  

import java.io.Serializable  

  

/** 

 * Description: 定义redis实现分布式锁的算法<br /> 

 * This program is protected by copyright IOL_SMALL_TAIL.<br /> 

 * Program Name: IOL_SMALL_TAIL<br /> 

 * Date: 2015年11月8日 

 * 

 * @author 王鑫 

 * @version 1.0 

 */  

public interface IRedisLockArithmetic extends Serializable {  

    /** 

     * 加锁算法<br /> 

     * @param key 

     * @return 

     */  

    public boolean lock(String key)  

      

    /** 

     * 解锁算法<br /> 

     * @param key 

     * @return 

     */  

    public boolean unLock(String key)  

}

二、redis分布式锁基础算法实现

[java] view plain copy print?

package com.iol.common.util.concurrent.locks.arithmetic  

  

import org.slf4j.Logger  

import org.slf4j.LoggerFactory  

  

import com.iol.common.util.concurrent.locks.IRedisComponent  

import com.iol.common.util.concurrent.locks.IRedisLockArithmetic  

  

/** 

 * Description: redis分布式锁基础算法实现<br /> 

 * This program is protected by copyright IOL_SMALL_TAIL.<br /> 

 * Program Name: IOL_SMALL_TAIL<br /> 

 * Date: 2015年11月9日 

 * 

 * @author 王鑫 

 * @version 1.0 

 */  

public class RedisLockBaseArithmetic implements IRedisLockArithmetic {  

    /** 

     *serialVersionUID 

     */  

    private static final long serialVersionUID = -8333946071502606883L  

      

    private Logger logger = LoggerFactory.getLogger(RedisLockBaseArithmetic.class)  

  

    /** 

     * redis操作方法 

     */  

    private IRedisComponent redisComp  

      

    /** 

     * 超时时间,以毫秒为单位<br /> 

     * 默认为5分钟 

     */  

    private long overtime = 5 * 60 * 1000L  

      

    /** 

     * 休眠时长,以毫秒为单位<br /> 

     * 默认为100毫秒 

     */  

    private long sleeptime = 100L  

      

    /** 

     * 当前时间 

     */  

    private long currentLockTime  

      

    /** 

     * @param redisComp the redisComp to set 

     */  

    public void setRedisComp(IRedisComponent redisComp) {  

        this.redisComp = redisComp  

    }  

  

    /** 

     * @param overtime the overtime to set 

     */  

    public void setOvertime(long overtime) {  

        this.overtime = overtime  

    }  

  

    /** 

     * @param sleeptime the sleeptime to set 

     */  

    public void setSleeptime(long sleeptime) {  

        this.sleeptime = sleeptime  

    }  

  

    /* (non-Javadoc) 

     * @see com.iol.common.util.concurrent.locks.IRedisLockArithmetic#lock(java.lang.String, java.lang.Long) 

     */  

    @Override  

    public boolean lock(String key) {  

        while(true) {  

            // 当前加锁时间  

            currentLockTime = System.currentTimeMillis()  

              

            if(redisComp.setIfAbsent(key, currentLockTime)) {  

                // 获取锁成功  

                logger.debug("直接获取锁{key: {}, currentLockTime: {}}", key, currentLockTime)  

                return true  

            } else {  

                //其他线程占用了锁  

                logger.debug("检测到锁被占用{key: {}, currentLockTime: {}}", key, currentLockTime)  

                Long otherLockTime = redisComp.get(key)  

                if(otherLockTime == null) {  

                    // 其他系统释放了锁  

                    // 立刻重新尝试加锁  

                    logger.debug("检测到锁被释放{key: {}, currentLockTime: {}}", key, currentLockTime)  

                    continue  

                } else {  

                    if(currentLockTime - otherLockTime >= overtime) {  

                        //锁超时  

                        //尝试更新锁  

                        logger.debug("检测到锁超时{key: {}, currentLockTime: {}, otherLockTime: {}}", key, currentLockTime, otherLockTime)  

                        Long otherLockTime2 = redisComp.getAndSet(key, currentLockTime)  

                        if(otherLockTime2 == null || otherLockTime.equals(otherLockTime2)) {  

                            logger.debug("获取到超时锁{key: {}, currentLockTime: {}, otherLockTime: {}, otherLockTime2: {}}", key, currentLockTime, otherLockTime, otherLockTime2)  

                            return true  

                        } else {  

                            sleep()  

                            //重新尝试加锁  

                            logger.debug("重新尝试加锁{key: {}, currentLockTime: {}}", key, currentLockTime)  

                            continue  

                        }  

                    } else {  

                        //锁未超时  

                        sleep()  

                        //重新尝试加锁  

                        logger.debug("重新尝试加锁{key: {}, currentLockTime: {}}", key, currentLockTime)  

                        continue  

                    }  

                }  

            }  

        }  

    }  

  

    /* (non-Javadoc) 

     * @see com.iol.common.util.concurrent.locks.IRedisLockArithmetic#unLock(java.lang.String) 

     */  

    @Override  

    public boolean unLock(String key) {  

        logger.debug("解锁{key: {}}", key)  

        redisComp.delete(key)  

        return true  

    }  

      

    /** 

     * 休眠<br /> 

     * @param sleeptime 

     */  

    private void sleep() {  

        try {  

            Thread.sleep(sleeptime)  

        } catch (InterruptedException e) {  

            throw new LockException("线程异常中断", e)  

        }  

    }  

}

package com.markor.zest.commonredis.utils

import lombok.extern.slf4j.Slf4j

import org.redisson.api.RLock

import org.redisson.api.RedissonClient

import org.springframework.beans.factory.annotation.Autowired

import org.springframework.stereotype.Component

import org.springframework.transaction.support.TransactionSynchronization

import org.springframework.transaction.support.TransactionSynchronizationManager

import java.util.concurrent.TimeUnit

/**

* @Author: lining

* @Description: redis加锁工具类

* @Date: create in 2021/12/24 16:38

*/

@Slf4j

@SuppressWarnings("ALL")

@Component

public class RedissonTemplate {

@Autowired

    private RedissonClient redissonClient

/**

    * 尝试加锁

    *

    * @param lockName    锁名字

    * @param waitTime    等待时间

    * @param releaseTime 释放时间

    * @param timeUnit    单位

    * @param callBack    返回对象

    * @param <T>        泛型

    * @return 返回

    */

    public T tryLock(String lockName,long waitTime,long releaseTime,TimeUnit timeUnit,RedissonLockCallBack callBack) {

RLock rLock =redissonClient.getLock(lockName)

T result =null

try {

boolean tryLock =this.tryLock(rLock, waitTime, releaseTime, timeUnit)

if (tryLock) {

this.unlock(rLock)

log.info("{}取到锁", lockName)

result = callBack.execute()

}else {

log.info("{}等待超时", lockName)

}

}catch (InterruptedException e) {

log.error("{} 锁发生中断异常!", lockName, e)

Thread.currentThread().interrupt()

}finally {

// 如果当前没有事务,且锁着呢,且是当前线程的

            if (!TransactionSynchronizationManager.isActualTransactionActive() &&

rLock.isLocked() &&rLock.isHeldByCurrentThread()) {

rLock.unlock()

}

}

return result

}

/**

    * 真正的加锁

    *

    * @param rLock      锁对象

    * @param waitTime    等待时间

    * @param releaseTime 释放时间

    * @param timeUnit    单位

    * @return 返回

    */

    private boolean tryLock(RLock rLock,long waitTime,long releaseTime,TimeUnit timeUnit)throws InterruptedException {

boolean bool

if (waitTime >0 &&releaseTime >0) {

bool = rLock.tryLock(waitTime, releaseTime, timeUnit)

}else if (releaseTime >0) {

bool = rLock.tryLock(0, releaseTime, timeUnit)

}else if (waitTime >0) {

bool = rLock.tryLock(waitTime, timeUnit)

}else {

bool = rLock.tryLock()

}

return bool

}

/**

    * redis解锁

    *

    * @param rLock 锁对象

    */

    public void unlock(RLock rLock) {

if (TransactionSynchronizationManager.isActualTransactionActive()) {

TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {

@Override

                public void afterCompletion(int status) {

log.info("{}释放锁",rLock.getName())

if (rLock.isLocked() &&rLock.isHeldByCurrentThread()) {

rLock.unlock()

}

}

})

}

}

}