当前位置:首页>滚动 > >正文

针对RedisTemplate分布式锁实现WatchDog

  • 2023-04-16 19:32:04来源:腾讯云


(相关资料图)

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

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

每日热讯!线索神秘派对的想法

谋杀之谜派对是一种有趣和令人兴奋的享受美好时光的方式。使用与谋杀之谜相关的文化标志——游戏和电影线索

江西赣州综合防治水土流失——治山理水 兴业富民

现代快报网是由凤凰出版传媒集团旗下的现代快报倾力打造的江苏新闻门户网站,目前在南京、苏州、无锡、常州

地铁6号线社林区间(漳州段)右线贯通 预计6月铺轨

地铁6号线社林区间(漳州段)右线贯通预计6月铺轨

想升职加薪吗?老板最喜欢这5类员工,最有可能成为“红人” 天天热议

大家在职场工作,每个人都有一个升职加薪的愿望,但是往往却很少有人可以如愿以偿。你知道吗?上级在选择提

为什么迪拜那么有钱_阿联酋迪拜是哪个国家 天天快资讯

今天小编肥嘟来为大家解答以上的问题。为什么迪拜那么有钱,阿联酋迪拜是哪个国家相信很多小伙伴还不知道,

环球热消息:维金斯复出!勇士国王半场鏖战,库里4次失误,前湖人悍将抢镜

首节比赛双方战成29-29平,比赛非常精彩,虽然勇士的失误比较多,库里、追梦格林的传球都被断,库里半节就3

当前视讯!【手慢无】狂降220元 WESCOM 27英寸4K显示器低至779元

炫彩高清,无边无界。WESCOMC2786IUY显示器,拥有3840*2160的超高清分辨率,呈现更多的细节画面。4K细腻IPS

油豆腐要怎么做才好吃_油豆腐怎么做好吃呢-天天时讯

1、你有多久没吃油豆腐了呢?无论是油豆腐还是水豆腐,给人感觉都是比较清淡的,在一堆堆肉类面前,油豆腐

猪鼻龟是什么龟_猪鼻龟更像是一只鳖

猪鼻龟是一种什么龟?猪鼻龟属于海龟,它的别名是贺飞龟。因为它的两只爪子看起来像乌龟,所以它也属于甲鱼

甘油三酯高吃什么食物降得快_甘油三酯高吃什么好 全球球精选

1、通常,对于仅血甘油三酯含量增高[2],而胆固醇含量正常的患者,应改变饮食结构,控制体重。2、另外还要

巴旦木仁孕妇可以吃吗_巴旦木仁 天天精选

1、巴旦木主要产在天山以南喀什绿洲的疏附、英吉沙、莎车、叶城等县。2、这些地方,我六七年前作环南疆行时

玩命公路暴走_关于玩命公路暴走介绍

玩命公路暴走,关于玩命公路暴走介绍这个很多人还不知道,我们一起来看看!1、一款刺激并且另类的竞速游戏。

绿色建筑行业市场深度研究2023

绿色建筑行业市场前景多大?党的二十大报告指出,加快发展方式绿色转型,积极稳妥推进碳达峰碳中和,推进工

荒野行动怎么隐藏背包 方法介绍-天天快播

荒野行动怎么隐藏背包方法介绍,

全球新消息丨科学驿站|科普产业发展:课外科学教育有很多开垦的空间

科学驿站|科普产业发展:课外科学教育有很多开垦的空间

当前速讯:突发!日媒:岸田文雄演讲场地传出爆炸声,一人被制服,现场有大量白烟

此外,NHK还公开了安保人员正在行动现场画面,报道称,一名男子被在现场的警察制服

旅游 | 有一种叫云南的生活:美在德宏

4月12日,“‘有一种叫云南的生活’·七彩云南美在德宏”专场新闻发布会在云南德宏瑞丽市姐告国门召开。6位

多家农商行下调存款利率 我们该怎样看待?

【多家农商行下调存款利率我们该怎样看待?】总体来看,此次下调存款利率,是2022年9月国有大行在下调存款

【天天热闻】华夏银行(600015):4月14日北向资金减持32.41万股

4月14日北向资金减持32 41万股华夏银行。近5个交易日中,获北向资金增持的有3天,累计净增持756 48万股。近

大话西游2符文画法攻略 大话西游2符文画法 世界报道

今天来聊聊关于大话西游2符文画法攻略,大话西游2符文画法的文章,现在就为大家来简单介绍下大话西游2符文

官方指导价格为 19.5888 万的大众 ID.4 X,你会考虑吗?-环球关注

随着汽车产品的研发升级,消费者的消费理念也在发生转变。如今的汽车消费者在购车选车时,考虑的方面会有很

天天精选!王府井集团2022年净利润同比下降85.45%

北京商报讯(记者刘卓澜王思琦)4月14日,王府井集团股份有限公司(以下简称“王府井集团”)发布2022年年

天天热推荐:多家水泥企业2022年利润腰斩,产能过剩时代海螺水泥为何逆势增产?

随着财报季逐渐谢幕,水泥企业的经营困境开始展露在投资者面前。3月22日,隶属于中国建材的天山股份(00087

28军军史_28军在85年整编以后军部在哪个城市 天天时讯

1、山西大同28军在85年整编以后年换防山西大同。2、希望能帮到你。本文分享完毕,希望对大家有所帮助。

送50岁的女人什么礼物好

50岁的女人一定要用心准备,因为女人的品质偏高,所以这个年纪的女人都会喜欢这些礼物,来分享一下送给50岁

扎实推进“百日行动” 为餐饮场所保驾护航 全球播资讯

为进一步加强燃气安全管理,深刻汲取事故教训,防范遏制燃气安全事故发生,消除安全隐患,江苏省徐州市铜山

【天天聚看点】兴发集团:拟2亿元-4亿元回购公司股份

金融界4月14日消息兴发集团(行情600141,诊股)公告,拟2亿元-4亿元回购公司股份,回购价格不超过40元 股,将

环球聚焦:交城县气象台发布大风蓝色预警【Ⅳ级/一般】【2023-04-14】

交城县气象台发布大风蓝色预警【Ⅳ级 一般】【2023-04-14】

每日聚焦:中国中建科创集团有限公司岗位招聘公告

中国中建科创集团有限公司(以下简称中建科创集团)组建于2022年10月,注册资本150亿元,是中国建筑股份有

猜您喜欢

Copyright ©  2015-2022 时代服装网版权所有  备案号:   联系邮箱: 514 676 113@qq.com