Redis 乐观锁与悲观锁

package com.mobanker.feature.credit.business.redis;

import javax.annotation.Resource;

import com.mobanker.feature.credit.common.constant.FeatureConstants;
import com.mobanker.feature.credit.common.utils.DateKit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.dianping.cat.message.Event;
import com.mobanker.framework.redis.template.RedisClientTemplate;


@Component(value="redisBusiness")
public class RedisBusinessImpl implements RedisBusiness {

    private Logger logger = LoggerFactory.getLogger(this.getClass());
    
    @Resource
    private RedisClientTemplate redisClientTemplate;

    @EETransaction(type = "business",name="RedisBusinessImpl.getValue")
    public String getValue(String key) {
        EE.logEvent("Monitor_business", "RedisBusinessImpl.getValue:", Event.SUCCESS, key);

        return redisClientTemplate.get(key);
    }

    @EETransaction(type = "business",name="RedisBusinessImpl.lock")
    public int lock(String key) {
        EE.logEvent("Monitor_business", "RedisBusinessImpl.lock:", Event.SUCCESS, key);

        logger.info("进入lock:key:{}", key);
        int flag = redisClientTemplate.setnx(key, getLockValue()).intValue();
        logger.info("进入lock:key:{},{}", key,"setnx状态:"+flag);
        if(flag==1){//拿到锁
            redisClientTemplate.expire(key, FeatureConstants.System.REDIS_LOCK_EXPIRE);
            return flag;
        }
        logger.info("进入lock:key:{},{}", key,"setnx 未获取锁");
        //key值存在判断是否过期
        String oldTime = redisClientTemplate.get(key);
        if(oldTime==null){
            return flag;
        }
        logger.info("进入lock:key:{},{}", key,"oldTime:"+ DateKit.compareTime(oldTime));
        if(DateKit.compareTime(oldTime)){
            oldTime = redisClientTemplate.getSet(key, getLockValue());
            //判断时间是否过期,如果过期则拿到锁
            logger.info("进入lock:key:{},{}", key,"如果过期则拿到锁:"+DateKit.compareTime(oldTime));
            if(DateKit.compareTime(oldTime)){
                redisClientTemplate.expire(key, FeatureConstants.System.REDIS_LOCK_EXPIRE);
                flag=1;
            }
        }
        logger.info("进入lock:key:{},{}", key,"结果:"+flag);
        return flag;
    }

    @org.jetbrains.annotations.NotNull
    @EETransaction(type = "business",name="RedisBusinessImpl.getLockValue")
    private String getLockValue(){
        EE.logEvent("Monitor_business", "RedisBusinessImpl.getLockValue:", Event.SUCCESS, "");

        return (DateKit.getNowLongTime()+FeatureConstants.System.REDIS_LOCK_KEY_TIME)+"";
    }


    @EETransaction(type = "business",name="RedisBusinessImpl.lockWait")
    public int lockWait(String key) throws InterruptedException {
        int flag = 0;
        logger.info("进入lockWait:key:{}", key);
        int timeout=FeatureConstants.System.REDIS_LOCK_WAIT_TIME*1000;
        while (timeout >= 0) {
            flag=lock(key);
            logger.info("进入lockWait:key:{},while value:{}", key,flag);
            if(flag==1){
                return flag;
            }
            timeout -= FeatureConstants.System.DEFAULT_ACQUIRY_RESOLUTION_MILLIS;
            /*延迟200 毫秒,  这里使用随机时间可能会好一点,可以防止饥饿进程的出现,即,当同时到达多个进程,
             *只会有一个进程获得锁,其他的都用同样的频率进行尝试,后面有来了一些进行,也以同样的频率申请锁,这将可能导致前面来的锁得不到满足.
             *使用随机的等待时间可以一定程度上保证公平性
             */
            Thread.sleep(FeatureConstants.System.DEFAULT_ACQUIRY_RESOLUTION_MILLIS);
        }
        logger.info("进入lockWait:key:{},{}", key,"结果:"+flag);
        EE.logEvent("Monitor_business", "RedisBusinessImpl.lockWait:", Event.SUCCESS, key);

        return flag;
    }
    
    

    @EETransaction(type = "business",name="RedisBusinessImpl.unlock")
    public void unlock(String key) {
        redisClientTemplate.del(key);
        EE.logEvent("Monitor_business", "RedisBusinessImpl.unlock:", Event.SUCCESS, key);

    }
    

    @EETransaction(type = "business",name="RedisBusinessImpl.setValue")
    public void setValue(String key, String msg) {
        setValue(key, msg, 0);
        EE.logEvent("Monitor_business", "RedisBusinessImpl.setValue:", Event.SUCCESS, key);


    }


    @EETransaction(type = "business",name="RedisBusinessImpl.setValue")
    public void setValue(String key, String msg, int time) {

        redisClientTemplate.set(key, msg);
        if (time != 0)
            redisClientTemplate.expire(key, time);
        EE.logEvent("Monitor_business", "RedisBusinessImpl.setValue:", Event.SUCCESS, key);

    }

    

    @EETransaction(type = "business",name="RedisBusinessImpl.delValue")
    public void delValue(String key) {
        redisClientTemplate.del(key);
        EE.logEvent("Monitor_business", "RedisBusinessImpl.delValue:", Event.SUCCESS, key);

    }

}

猜你喜欢

转载自blog.csdn.net/qq_20672231/article/details/78422552