當前位置:主頁 > 要聞 > 正文
    針對RedisTemplate分布式鎖實現WatchDog
    來源:騰訊云作者:洞察網2023-04-21 16:20:18


    (資料圖片)

    在此之前,去看了下Redission的實現原理,不過在開發中,原本的代碼使用RedistTemplate實現的,也不太想換,所以我想了下,不如自己實現要給WatchDog。

    我的想法是,在用戶加上鎖的時候開啟個定時任務線程,并且在定時任務中,判斷原線程isAlive狀態進行“續命”。

    下面是代碼(在這里面為了方便,未使用的是HuTool.CornUtil來實現動態定時任務):

    /** * Title * * @ClassName: LockUtil * @Description:鎖工具類,通過內部枚舉類實現單例,防止反射攻擊 * @author: Karos * @date: 2023/1/4 0:17 * @Blog: https://www.wzl1.top/ */package cn.katool.lock;import cn.hutool.core.util.BooleanUtil;import cn.hutool.core.util.ObjectUtil;import cn.hutool.cron.CronUtil;import cn.hutool.cron.task.Task;import cn.katool.Config.LockConfig;import cn.katool.Exception.ErrorCode;import cn.katool.Exception.KaToolException;import cn.katool.other.MethodIntefaceUtil;import com.qiniu.util.StringUtils;import lombok.SneakyThrows;import lombok.extern.slf4j.Slf4j;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Scope;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Component;import org.springframework.util.ObjectUtils;import javax.annotation.Resource;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.TimeUnit;@Component@Scope("prototype")@Slf4jpublic class LockUtil {        @Resource        RedisTemplate redisTemplate;        private LockUtil(){        }        private static boolean isOpenCorn=false;        /**         * 帶看門狗機制上鎖         * @param lockObj         * @return         */        public boolean DistributedLock(Object lockObj){                try {                        return DistributedLock(lockObj,null,null);                } catch (KaToolException e) {                        throw new RuntimeException(e);                }        }        @Resource        LockConfig lockConfig;        //加鎖        /**         * 無看門狗機制上鎖         * @param obj         * @param exptime         * @param timeUnit         * @return         * @throws KaToolException         */        public boolean DistributedLock(Object obj,Long exptime,TimeUnit timeUnit) throws KaToolException {                if (ObjectUtil.isEmpty(obj)){                        throw new KaToolException(ErrorCode.PARAMS_ERROR," Lock=> 傳入obj為空");                }                Boolean isDelay=false;                if (ObjectUtil.isAllEmpty(exptime,timeUnit)){                        isDelay=true;                }                if(ObjectUtil.isEmpty(exptime)){                        exptime= lockConfig.getInternalLockLeaseTime();;                }                if (ObjectUtils.isEmpty(timeUnit)){                        timeUnit=lockConfig.getTimeUnit();                }                //線程被鎖住了,就一直等待                DistributedAssert(obj);                Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("Lock:"+obj.toString(), "1", exptime, timeUnit);                log.info("katool=> LockUntil => DistributedLock:{} value:{} extime:{} timeUnit:{}",obj.toString(), "1", exptime, timeUnit);                //實現看門狗                if (isDelay){                        if (LockUtil.isOpenCorn==false){                                //如果同一個項目之前打開過,那么先關閉,避免重復啟動                                CronUtil.stop();                                //支持秒級別定時任務                                CronUtil.setMatchSecond(true);                                //定時服務啟動                                CronUtil.start();                                LockUtil.isOpenCorn=true;                        }                        Thread thread = Thread.currentThread();                        TimeUnit finalTimeUnit = timeUnit;                        Long finalExptime = exptime;                        class TempClass{                                public String scheduleId;                        }                        final TempClass tempClass = new TempClass();                        tempClass.scheduleId=CronUtil.schedule("0/30 * * * * ?", new Task() {                                @SneakyThrows                                @Override                                public void execute() {                                        boolean alive = thread.isAlive();                                        if (alive) {                                                delayDistributedLock(obj, finalExptime>=3?(finalExptime / 3):finalExptime, finalTimeUnit);                                                return;                                        } else {                                                if (tempClass.scheduleId==null||"".equals(tempClass.scheduleId)){                                                        return;                                                }                                                CronUtil.remove(tempClass.scheduleId);                                                DistributedUnLock(obj);                                                return;                                        }                                }                        });                }                return BooleanUtil.isTrue(aBoolean);        }        //檢鎖        public void DistributedAssert(Object obj) throws KaToolException {                if (ObjectUtils.isEmpty(obj)){                        throw new KaToolException(ErrorCode.PARAMS_ERROR," Lock=> 傳入obj為空");                }                while(true){                        Object o = redisTemplate.opsForValue().get("Lock:" + obj.toString());                        if (ObjectUtils.isEmpty(o))return;                }        }        //延期        public boolean delayDistributedLock(Object obj,Long exptime,TimeUnit timeUnit) throws KaToolException {                if (ObjectUtils.isEmpty(obj)){                        throw new KaToolException(ErrorCode.PARAMS_ERROR," Lock=> 傳入obj為空");                }                Boolean aBoolean = redisTemplate.opsForValue().setIfPresent("Lock:"+obj.toString(), "1", exptime, timeUnit);                log.info("katool=> LockUntil => delayDistributedLock:{} value:{} extime:{} timeUnit:{}",obj.toString(), "1", exptime, timeUnit);                return BooleanUtil.isTrue(aBoolean);        }        //釋放鎖        public boolean DistributedUnLock(Object obj) throws KaToolException {                if (ObjectUtils.isEmpty(obj)){                        throw new KaToolException(ErrorCode.PARAMS_ERROR," Lock=> 傳入obj為空");                }                Boolean aBoolean = redisTemplate.delete("Lock:" + obj.toString());                log.info("katool=> LockUntil => unDistributedLock:{} isdelete:{} ",obj.toString(),true);                return BooleanUtil.isTrue(aBoolean);        }        //利用枚舉類實現單例模式,枚舉類屬性為靜態的        private enum SingletonFactory{                Singleton;                LockUtil lockUtil;                private SingletonFactory(){                        lockUtil=new LockUtil();                }                public LockUtil getInstance(){                        return lockUtil;                }        }        @Bean("LockUtil")        public static LockUtil getInstance(){                return SingletonFactory.Singleton.lockUtil;        }}

    [責任編輯:linlin]

    標簽:

    評論排行
    熱門話題
    最近更新
    亚洲人成无码久久电影网站| 亚洲女人18毛片水真多| 亚洲邪恶天堂影院在线观看| 狠狠亚洲狠狠欧洲2019| 亚洲精品偷拍视频免费观看| 日韩欧美亚洲国产精品字幕久久久| 亚洲欧美国产日韩av野草社区| 亚洲日本一区二区一本一道| 亚洲avav天堂av在线网毛片| 亚洲av无码专区青青草原| 亚洲人成图片网站| 亚洲人成影院午夜网站| 亚洲成在人线中文字幕| 亚洲小说区图片区| 亚洲理论片中文字幕电影| 亚洲理论片中文字幕电影| 亚洲午夜电影一区二区三区| 亚洲国产日韩在线| 国产成人精品日本亚洲11| 亚洲中文字幕无码久久2020| 亚洲熟妇成人精品一区| 亚洲中文字幕无码爆乳| 亚洲乱码av中文一区二区| 无码亚洲成a人在线观看| 国产亚洲综合一区二区三区| 亚洲国产精品综合久久网络| 亚洲视频一区二区| 国产亚洲精久久久久久无码| 亚洲2022国产成人精品无码区| 亚洲精品色播一区二区| 亚洲av永久无码天堂网| 日韩在线视精品在亚洲| 亚洲视频在线免费| 久久亚洲国产精品一区二区| 亚洲av综合avav中文| 亚洲精品国产成人| 亚洲日韩精品无码AV海量| 怡红院亚洲红怡院在线观看| 亚洲一级片内射网站在线观看| 日韩亚洲人成在线综合| 狠狠亚洲狠狠欧洲2019|