当前位置:首页 >科技 > 正文

针对RedisTemplate分布式锁实现WatchDog
2023-04-21 16:08:19    腾讯云


(相关资料图)

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

关键词:

下一篇:
上一篇:

针对RedisTemplate分布式锁实现WatchDog

天天动态:2023年百色市职工运动会开幕

当前快报:哪些牛肉块可以变成炖肉?

打完玻尿酸后还可以脂肪填充吗 世界动态

南通报业大厦水空调系统维保工程项目(二次)竞争性磋商公告

【原唱歌曲】我们是绿色轻骑兵

当前快播:北京西城区开展消防和反恐防暴演练

LPR连续8个月“原地踏步” 二季度实体经济融资成本仍有望保持低位

浙大学生因辱华言论被拒录公务员事件简单介绍

华光新材亮相2023中国制冷展|每日焦点

北京长峰医院火灾事故初步调查结果公布:医院内部施工作业火花引发 天天快资讯

姜子牙剧情深度解析_姜子牙剧情 每日报道

农发行安顺分行总结一季度工作成效部署下一步工作

全球最新:华星光电招聘_化星

万象天地|新商圈地标,预见城北无限可能

农业农村部:预计二季度末生猪价格有望趋于平缓|世界视讯

曼城女足队长:我可不想防守哈兰德,他这样的球员该如何阻止呢?

浩方对战平台无法连接服务器_为什么我进入浩方对战平台注册的时候总是该页无法显示 焦点播报

记者:欧洲俱乐部联盟成立,但欧洲俱乐部协会不承认其合法性 当前热闻

【世界热闻】官方:预计未来5到10年农业农村投资需求近15万亿元

世界新资讯:曼联出局罪人马奎尔 凭一己之力葬送红魔欧战之路

多地出台政策鼓励生育,浙江上虞三孩家庭购房可获30万元房票-全球热闻

每日热点:新疆喀什首座万达广场于4月20日盛大开业!带动城市体验式商业变革升级

SpaceX“星舟”重型运载火箭发射升空后爆炸 每日看点

全球速讯:黄赤交角变化的影响及图像演示_黄赤交角

大熊猫“林惠”已确认死亡!曾长期用工业竹喂养,本可以10月回家_全球快消息

浙江美大:一季度归母净利润同比下滑17.2%

“拉卡拉自曝跳码”!支付行业顽疾为何屡禁不止?

关注:西藏那曲深入无人区 巡护监测羌塘国家级保护区

动圈话筒放大器_动圈话筒|天天快消息

焦点速看:联手高科技服务校园体育,暨大体育学院与英气科技签约合作

金山云急升逾14% WPS宣布将推出“WPS AI”

Q1净利润同比下降24% 特斯拉美股盘前跌6%

横店影视(603103):4月20日北向资金增持1.03万股|环球看热讯

杭州萧山兴议社区:提高消防意识 共创平安家园

埋头苦干的人拼命硬干的人舍身求法的人 埋头苦干的人拼命硬干的人