當前位置:主頁 > 要聞 > 正文
    針對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]

    標簽:

    評論排行
    熱門話題
    最近更新
    久久精品国产亚洲香蕉 | 亚洲an日韩专区在线| 国产亚洲精品精品国产亚洲综合| 亚洲AV无码一区二区三区性色 | 亚洲Aⅴ无码一区二区二三区软件| 亚洲GV天堂无码男同在线观看| 亚洲色丰满少妇高潮18p| 亚洲国产系列一区二区三区| 亚洲av无码一区二区三区天堂古代| 亚洲成人在线免费观看| 亚洲噜噜噜噜噜影院在线播放| 91嫩草亚洲精品| 亚洲伊人久久大香线蕉结合| 亚洲国产成人久久精品app| 亚洲Av无码一区二区二三区| 亚洲av无码不卡久久| 亚洲一日韩欧美中文字幕在线| 亚洲中文字幕AV每天更新| 亚洲人成电影网站色www| 亚洲av日韩专区在线观看| 亚洲成年看片在线观看| 亚洲一级片免费看| 亚洲中文字幕第一页在线 | 中文字幕精品亚洲无线码二区| 亚洲午夜无码久久久久| 亚洲AV综合色区无码另类小说| 亚洲电影免费在线观看| 亚洲精品日韩中文字幕久久久| 亚洲午夜久久久精品电影院| 亚洲中文字幕无码av永久| 国产偷国产偷亚洲清高APP| 亚洲午夜日韩高清一区| 亚洲爆乳无码专区| 亚洲精品在线视频观看| 国产精品高清视亚洲精品| 亚洲av日韩综合一区二区三区| 亚洲欧洲日产国码高潮αv| 亚洲啪啪AV无码片| 中文字幕亚洲综合精品一区| 中文字幕亚洲男人的天堂网络 | 亚洲va久久久噜噜噜久久狠狠|