天天看热讯:针对RedisTemplate分布式锁实现WatchDog
来源:腾讯云    2023-04-22 10:30:32


(资料图片)

在此之前,去看了下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分布式锁...

在此之前,去看了下Redission的实现原理,不过在开发中,原本的代码使用RedistTemplate实现的,也不太想换

2023-04-22

天天观点:浙江震元:2022年净利润增长0...

4月21日电,浙江震元公布2022年年度报告,报告期实现营业收入41 45亿元,同比增长14 77%;归属于上市公司股东

2023-04-22

北京北传科技发展有限公司原党总支书记...

https: mp weixin qq com s PSnqpimF7pYaT1YRLB5F1g

2023-04-22

分宜工业经济高质量发展步履坚实

江西新闻客户端讯(江西日报全媒体记者邹宇波通讯员廖欢、李超峰)近日,分宜县分别获评2022年度全省工业高

2023-04-22

精彩看点:宏碁发布最新商用笔记本Trave...

2023年4月20日在主题为“探索新平衡”的宏碁全球春季新品发布会上,宏碁发布多款全新TravelMate航海家商务

2023-04-22

东京奥运会奖牌材料成本_东京奥运会奖牌...

欢迎观看本篇文章,小勉来为大家解答以上问题。东京奥运会奖牌材料成本,东京奥运会奖牌的成本费用是多少很

2023-04-22

甘肃这位真人地位仅次老子 《道德经》...

尹喜,又名尹子,字文公,号文始先生、文始真人、关尹。先秦天下十豪,周朝大夫、大将军,先秦时邽县人,今

2023-04-22

华为声明:“孟晚舟要去美国出差”系谣言

三言科技4月21日消息,今日华为集团发布声明称,近期网上流传“孟晚舟要去美国出差”,纯属造谣,孟晚舟女

2023-04-22

芭乐和莲雾是一种水果吗?

芭乐和莲雾不是一种水果。芭乐外形像梨,里面有白芯的和红芯的两种。而成熟的莲雾是红色的,也比芭乐小。水

2023-04-22

每日速讯:硫氢化钠32%液体,石油副产商...

交易商品牌 产地交货地最新报价硫氢化钠 硫氢化钠32%液体,石油副产山东星泰化工有限公司清源石化山东省

2023-04-22

焦点热讯:平江县南江镇:手把青秧抛 “...

红网时刻岳阳4月21日讯(通讯员周婵娟)四月农家闲人少,陇上秧苗待入田。眼下正是抛秧时节。4月21日,在“

2023-04-22

看点:新丰小吃2022年净利921.55万同比...

新丰小吃2022年净利921 55万同比增长83 29%投资收益增加2023 4 2120:04:32挖贝网易凡挖贝网4月21日,新丰小吃(872

2023-04-22

当前要闻:最美丽的相遇600字友谊开头_...

1、友谊,是最美丽的遇见在茫茫人海中,回眸瞬间,定格永恒。2、——题记友谊,是心与心的结合开出最美的花

2023-04-22

外交部:针对韩方涉台错误言论,中方已...

中国外交部发言人汪文斌4月21日主持例行记者会。有记者提问:韩国政府就昨天中国外交部例行记者会上有关韩

2023-04-22

天天看热讯:中建八局上海公司临港C5B-1...

中建八局上海公司临港C5B-11项目为工友送上爱心夜宵

2023-04-22

马斯克星舰发射分离失败,但很多人都给...

01星舰发射失败马斯克的“星舰”梦又要延迟了。4月20日,世界各地的很多人们都关注这个地方,马斯克创立的S

2023-04-22

安源管道2022年净利1975.07万同比下滑1....

安源管道2022年净利1975 07万同比下滑1 82%其他收益减少2023 4 2119:18:05挖贝网白莹挖贝网4月21日,安源管道(870

2023-04-22

今日报丨今日怎么在qq空间里发音频_怎么...

1、打开浏览器,进入搜狗搜索。2、在搜索栏中搜索关键字,QQ空间,点击进入QQ空间的官方网址,如图。3、确

2023-04-22

2023上半年四川省文化和旅游厅关于四川...

根据《四川省文化和旅游厅关于下属事业单位2023年上半年公开招聘工作人员公告》规定,现将我厅下属事业单位

2023-04-22

环球观热点:非凡的公主希瑞国语版百度...

今天来聊聊关于非凡的公主希瑞国语版百度云,720p,非凡的公主希瑞国语版的文章,现在就为大家来简单介绍下

2023-04-22