针对RedisTemplate分布式锁实现WatchDog_全球实时

来源:腾讯云时间:2023-04-21 15:52:16


(资料图片)

在此之前,去看了下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;        }}

标签:

相关阅读

推荐阅读

南京发布房票安置政策 新购房屋将免征契税

南京发布房票安置政策 新购房屋将免征契税

南京市建委牵头印发 《南京市国有土地上住宅房屋征收房票安置暂行办法》(简称《暂行办法》),明确当购房成交价格不超过房票票面金额时,新 更多

2023-03-27 10:44:55
今日最新!2023年一级建造师《工程经济》历年真题精选0326_一级建造师

今日最新!2023年一级建造师《工程经济》历年真题

2023年一级建造师《工程经济》考试共80题,分为单选题和多选题。小编为您整理历年真题10道,附答案解析,供您考前自测提升!1、下列经济效果评更多

2023-03-27 10:12:28
600377股票 有色金属股票还没有涨停的有哪些 天天速读

600377股票 有色金属股票还没有涨停的有哪些 天

最近小编看到大家都在讨论600377股票 有色金属股票还没有涨停的有 更多

2023-03-27 09:58:50
预计今春沙尘过程偏多,沙尘天气是否呈现变多趋势?

预计今春沙尘过程偏多,沙尘天气是否呈现变多趋势

近日,今年以来强度最强、影响范围最广的沙尘天气侵袭多地,波及20个省(区、市),影响面积超过485万平方公里。本次过程强度达到强沙尘暴等级更多

2023-03-27 09:54:47
央行2月金融数据出炉!钱去哪了扬城住户存款增20.3%

央行2月金融数据出炉!钱去哪了扬城住户存款增20.3%

近日,央行2月金融数据出炉,记者从中国人民银行扬州中心支行获悉,2月末扬城住户存款余额5540 8亿元,银行存款产品备受青睐。为何市民偏爱银更多

2023-03-27 09:38:56
快资讯:3亩鱼池成“聚宝盆”每年40万尾小金鱼批量流向全国

快资讯:3亩鱼池成“聚宝盆”每年40万尾小金鱼批

陆兆生和他的金鱼池。司新利摄3亩多地的面积,被分割成56个鱼池,里面游动着一尾尾色彩艳丽的小金鱼,像一朵朵花儿在水中绽放,这就是景区城北更多

2023-03-27 09:49:50
小额贷款利息-我想问一下小额贷款一般利息多少

小额贷款利息-我想问一下小额贷款一般利息多少

最近这段时间总有小伙伴问小编小额贷款利息-我想问一下小额贷款一般 更多

2023-03-27 08:54:27
主板注册制第一股今日开启网上申购 有哪些变与不变?

主板注册制第一股今日开启网上申购 有哪些变与不

3月27日,沪市主板注册制第一股中重科技(603135)、深市主板注册制第一股登康口腔(001328)将进行新股申购。根据发行安排,首批沪深主板注册制新更多

2023-03-27 07:54:18
+ 点击查看更多精彩
今日最新!2023年一级建造师《工程经济》历年真题精选0326_一级建造师
    2023年一级建造师《工程经济》考试共80题,分为单选题和多选题。...
600377股票 有色金属股票还没有涨停的有哪些 天天速读
    最近小编看到大家都在讨论600377股票 有色金属股票还没有涨停的有
预计今春沙尘过程偏多,沙尘天气是否呈现变多趋势?
    近日,今年以来强度最强、影响范围最广的沙尘天气侵袭多地,波及2...
央行2月金融数据出炉!钱去哪了扬城住户存款增20.3%
    近日,央行2月金融数据出炉,记者从中国人民银行扬州中心支行获悉...
快资讯:3亩鱼池成“聚宝盆”每年40万尾小金鱼批量流向全国
    陆兆生和他的金鱼池。司新利摄3亩多地的面积,被分割成56个鱼池,...
小额贷款利息-我想问一下小额贷款一般利息多少
    最近这段时间总有小伙伴问小编小额贷款利息-我想问一下小额贷款一...