针对RedisTemplate分布式锁实现WatchDog

2023-04-17 08:45:34 来源:腾讯云


(资料图片)

在此之前,去看了下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
针对RedisTemplate分布式锁实现WatchDog

在此之前,去看了下Redission的实现原理,不过在开发......更多>

早知道:上市公司独立董事制度全面改革;宁德时代钠离子电池首发落地
早知道:上市公司独立董事制度全面改革;宁德时代钠离子电池首发落地

上市公司独立董事制度全面改革,履职更具“独立性”;......更多>

广发证券:AI投资会有一段时间调整期,下一阶段依靠两方面外界因素_全球快资讯
广发证券:AI投资会有一段时间调整期,下一阶段依靠两方面外界因素_全球快资讯

广发证券最新研报表示,AI方面的投资会有一段时间的调......更多>

环球动态:华泰证券:关注AI大模型在终端侧的轻量化应用
环球动态:华泰证券:关注AI大模型在终端侧的轻量化应用

华泰证券研报表示,模型压缩技术是实现AI大模型在边 ......更多>

排行推荐

旺能环境:签署《监利市餐厨垃圾综合处理和资源化利用项目特许经营协议》|世界简讯
旺能环境:签署《监利市餐厨垃圾综合处理和资源化利用项目特许经营协议》|世界简讯
旺能环境(002034):签署《监利市餐厨垃圾综合处理和资... 更多>
环球微头条丨中证报:因城施策持续显效,楼市企稳迹象渐增
环球微头条丨中证报:因城施策持续显效,楼市企稳迹象渐增
中指研究院认为,各地因城施策支持力度不断增强,短期... 更多>
证券日报:旅游市场加快复苏, “五一”出行热度高涨
证券日报:旅游市场加快复苏, “五一”出行热度高涨
携程旗下FlightAi市场洞察平台数据显示,截至4月14日... 更多>
中信建投:光伏估值处于低位 看好一季报业绩超预期方向_世界即时
中信建投:光伏估值处于低位 看好一季报业绩超预期方向_世界即时
中信建投最新研报表示,市场对于光伏板块预期悲观,主... 更多>
世界今日报丨俄罗斯总统普京会见李尚福
据新华社,当地时间4月16日,俄罗斯总统普京在莫斯科... 更多>
全球今热点:经济日报:确保电力平稳迎峰度夏
文章称,随着社会生产生活快速恢复,今年迎峰度夏期间... 更多>
经济日报:多渠道拓展国产大豆消费|全球滚动
国家粮食和物资储备局科学研究院首席研究员李爱科撰文... 更多>
天天热讯:国内成品油零售价将迎今年来最大涨幅,92号汽油每升上涨0.4元左右
受国际油价大幅攀升影响,国内汽柴油零售价结束连跌走... 更多>
【环球新视野】产业趋势投资中,如何赚“认知差”的钱?
投资进化论系列:消除不确定性这一轮令人瞠目结舌的AI... 更多>
全球观热点:写给所有散户的一封信:换手率大于7%意味着什么?看懂少走弯路!
所谓市场,就是交易场所。市场本身不产生利润。所谓赚... 更多>
上海谊众紫杉醇聚合物胶束新增适应症临床获批
$上海谊众(SH688091)$从国家药品监督管理局药品评审中... 更多>
机构开始覆盖光库_观点
光库周五涨13 69%。机构覆盖开始了。海通吹响号角,... 更多>
30年期国债期货即将上市 首批3个合约将于4月21日交易
具体而言,中金所在《通知》中称,30年期国债期货首批... 更多>
时讯:好奇和天真
$东阿阿胶(SZ000423)$自己的签名档从来到雪球就是这个... 更多>

世界动态:今年应该买什么(主线顺序

浅谈华晨中国01114的估值和安全边际

【价值重估】医药板块逆势上涨,AI

滚动:无名最终票房具体详细内容是

当前资讯!人头攒动 掌声连连!广交

世界新消息丨持有兴业银行的投资者

埃安肖勇:特斯拉不是不能战胜

宁德时代钠离子电池首发落地奇瑞车

继续讨论不同轮动日的影响

4月16日:|世界快资讯