【环球新视野】针对RedisTemplate分布式锁实现WatchDog
2023-04-21 16:22:48
【资料图】
在此之前,去看了下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
- 全球观速讯丨成都轨道交通7号线工程获中国土木工程“詹天佑奖”
- 什么是牛胸肌? 每日快讯
- 全球要闻:4月21日原油市场行情:油价继续下跌向缺口靠近
- 餐(饮)具消毒“码”上见
一键溯源让百姓用上放心碗筷 - 【环球新视野】宏碁发布全新传奇Go 16,锐龙7000+RTX40打造更强生产力!
- 上海土拍战况激烈:已成交410亿,建发未如愿,华发中奖明星地块
- 丹凤县气象台发布雷雨大风黄色预警【Ⅲ级/较重】 全球最资讯
- 【速看料】十八少年话凉州
- 长峰医院火灾事故原因:施工过程中火花引燃挥发物
- 59+11!53+13!杜兰特力挺你,哈登果然兑现承诺,帮你完成大满贯
- 兴力工程公司联合鑫顺产业集团开展纪委委员联学活动 视点
- 【天天播资讯】第一种形态十四种方式有哪些_第一种形态十四种方式
- 创新乡村旅游业态 苏州多个产品和项目入选“省级示范”|今日要闻
- 电脑制图入门教程_怎样在电脑上设计制图
- “对飙局”两人砍下40+,穆雷助掘金再胜森林狼_世界新动态
- 本赛季欧冠克罗斯触球传球次数均领跑,传球成功率94% 天天新资讯
- 观察:今天最新消息 太湖平均水位3.07米 为近20年同期最低
- 每日动态!古特雷斯呼吁苏丹冲突各方停火三日
- 天天消息!京郊度假酒店“五一”降温
- AC米兰上一次成为欧冠四强时,世界是这样的……
- 特斯拉起诉前工程师盗取超算机密,最终双方和解
- 【焦点热闻】天水市委依法治市办对秦安县开展专项监督检查
- 焦点热讯:解元会元状元连中三元是什么意思_解元会元状元
- 环球热推荐:长沙4宗熔断地块摇号名单出炉!将于4月25日定主
- 全省第一!济南高新区29个人工智能应用场景入选省级名单
- ST目药2022年业绩预告更正:预计亏损6500万元-7200万元
- 调查显示:中国内地小微企业料现稳健复苏
- 虫草花是什么东西长出来的_虫草花是什么|世界微资讯
- 益客食品(301116.SZ)发2022年度业绩,净利润5174.36万元,同比减少55.83%,每10股派0.5元
x
广告
x
广告