Redis分布式锁过期时间续约问题

2024-01-05 18:40

本文主要是介绍Redis分布式锁过期时间续约问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Redis实现分布式锁的自动续时间问题

  • Redis实现分布式锁的自动续命问题
    • 首先了解lua脚本,原子性。
    • HashedWheelTimer时间轮异步定时执行
    • Redis通过异步定时使用lua脚本重置分布式锁的过期时间

Redis实现分布式锁的自动续命问题

首先了解lua脚本,原子性。

lua脚本在Redis中是原子性的,就是在执行lua脚本的时候,不会被其他外部命令干扰,但是不能回滚,结果错就是错了,结果没有回滚一说。

HashedWheelTimer时间轮异步定时执行

HashedWheelTimer的demo使用演示

package com.lxx;import io.netty.util.HashedWheelTimer;
import io.netty.util.Timeout;import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;public class shiyan {//HashedWheelTimer异步执行static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");public static void main(String[] args) {Date date = new Date(System.currentTimeMillis());System.out.println(formatter.format(date));testTimeout();System.out.println("结束吧");//现在又想取消掉这个任务
//        if(!newTimeout.isExpired()){
//            newTimeout.cancel();
//        }}public static void testTimeout() {HashedWheelTimer timer = new HashedWheelTimer();
//        timer.newTimeout(new TimerTask() {
//            @Override
//            public void run(Timeout timeout) throws Exception {
//                Date datee = new Date(System.currentTimeMillis());
//                System.out.println("10s后执行" + formatter.format(datee));
//            }
//        }, 10, TimeUnit.SECONDS);Timeout newTimeout = timer.newTimeout(timerTask -> {Date datee = new Date(System.currentTimeMillis());System.out.println("10s后执行" + formatter.format(datee));testTimeout();//回调自己,在进行10s执行一次。}, 10, TimeUnit.SECONDS);//10s后执行Lambda表达式/*现在又想取消掉这个任务if (!newTimeout.isExpired()) {newTimeout.cancel();}*/}
}

执行结果:
在这里插入图片描述

Redis通过异步定时使用lua脚本重置分布式锁的过期时间

使用StringRedisTemplate,因为使用的序列化问题。不建议使用RedisTemplate,如果使用,要改序列化。可自行搜索。

package com.lxx;import io.netty.util.HashedWheelTimer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Arrays;
import java.util.concurrent.TimeUnit;@RestController
@RequestMapping("shiyan")
public class RedisSuo {@Autowiredprivate StringRedisTemplate redisTemplate;//lua脚本如果有当前key那么就去重置当前key的过期时间返回1,否则返回0。private static String luas = "if (redis.call('exists',KEYS[1]) == 1) then redis.call('expire',KEYS[1], ARGV[1]) return 1 end return 0";private static DefaultRedisScript luaaa = new DefaultRedisScript(luas, Boolean.class);//讲lua脚本封装到类中private HashedWheelTimer timer = new HashedWheelTimer();private String key = "suo";@RequestMapping("select")public Boolean selectById(String valueid, int time) {//redis底层执行的是SET K V NX EX 60Boolean status = redisTemplate.opsForValue().setIfAbsent(key, valueid, time, TimeUnit.SECONDS);//加锁以及超时时间if (status) {try {//核心是异步多长时间后执行就可以。watchdog(time);//执行业务代码Thread.sleep(15 * 1000);} catch (Exception e) {throw new RuntimeException(e.getMessage());} finally {//释放锁资源。底层就是DEL kredisTemplate.delete(key);}return true;} else {System.out.println("服务器正忙请稍后再试..........");return false;}}public void watchdog(int time) {timer.newTimeout(timerTask -> {Boolean execute = (Boolean) redisTemplate.execute(luaaa, Arrays.asList(key), String.valueOf(time));//意思就是执行luaaa,key给KEYS[1],time给ARGV[1]if (execute) {System.out.println("如果当前的key有,并且已经续期了,那么现在需要递归判断下一次是否还有key。");watchdog(time);} else {System.out.println("没有key了。锁已经没了,就不会进行续期了");}}, time / 3, TimeUnit.SECONDS);//time的三分之一时间去执行看有没有key,有重置过期时间,没有就什么都不做。}
}

请求,时间为30s。代码里面是15s,会进行续命。
在这里插入图片描述
执行结果。进行了一次续命。
在这里插入图片描述
走到了23
在这里插入图片描述
重置续命后30
在这里插入图片描述
附上Redisson官网

在这里插入图片描述
最后用Redisson的API来实现分布式锁的应用。
结束!感谢观看!

这篇关于Redis分布式锁过期时间续约问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/573795

相关文章

解决pandas无法读取csv文件数据的问题

《解决pandas无法读取csv文件数据的问题》本文讲述作者用Pandas读取CSV文件时因参数设置不当导致数据错位,通过调整delimiter和on_bad_lines参数最终解决问题,并强调正确参... 目录一、前言二、问题复现1. 问题2. 通过 on_bad_lines=‘warn’ 跳过异常数据3

解决RocketMQ的幂等性问题

《解决RocketMQ的幂等性问题》重复消费因调用链路长、消息发送超时或消费者故障导致,通过生产者消息查询、Redis缓存及消费者唯一主键可以确保幂等性,避免重复处理,本文主要介绍了解决RocketM... 目录造成重复消费的原因解决方法生产者端消费者端代码实现造成重复消费的原因当系统的调用链路比较长的时

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499

kkFileView启动报错:报错2003端口占用的问题及解决

《kkFileView启动报错:报错2003端口占用的问题及解决》kkFileView启动报错因office组件2003端口未关闭,解决:查杀占用端口的进程,终止Java进程,使用shutdown.s... 目录原因解决总结kkFileViewjavascript启动报错启动office组件失败,请检查of

Redis MCP 安装与配置指南

《RedisMCP安装与配置指南》本文将详细介绍如何安装和配置RedisMCP,包括快速启动、源码安装、Docker安装、以及相关的配置参数和环境变量设置,感兴趣的朋友一起看看吧... 目录一、Redis MCP 简介二、安www.chinasem.cn装 Redis MCP 服务2.1 快速启动(推荐)2.

Java获取当前时间String类型和Date类型方式

《Java获取当前时间String类型和Date类型方式》:本文主要介绍Java获取当前时间String类型和Date类型方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录Java获取当前时间String和Date类型String类型和Date类型输出结果总结Java获取

Python实现批量提取BLF文件时间戳

《Python实现批量提取BLF文件时间戳》BLF(BinaryLoggingFormat)作为Vector公司推出的CAN总线数据记录格式,被广泛用于存储车辆通信数据,本文将使用Python轻松提取... 目录一、为什么需要批量处理 BLF 文件二、核心代码解析:从文件遍历到数据导出1. 环境准备与依赖库

SpringBoot 异常处理/自定义格式校验的问题实例详解

《SpringBoot异常处理/自定义格式校验的问题实例详解》文章探讨SpringBoot中自定义注解校验问题,区分参数级与类级约束触发的异常类型,建议通过@RestControllerAdvice... 目录1. 问题简要描述2. 异常触发1) 参数级别约束2) 类级别约束3. 异常处理1) 字段级别约束

Python错误AttributeError: 'NoneType' object has no attribute问题的彻底解决方法

《Python错误AttributeError:NoneTypeobjecthasnoattribute问题的彻底解决方法》在Python项目开发和调试过程中,经常会碰到这样一个异常信息... 目录问题背景与概述错误解读:AttributeError: 'NoneType' object has no at

Spring的RedisTemplate的json反序列泛型丢失问题解决

《Spring的RedisTemplate的json反序列泛型丢失问题解决》本文主要介绍了SpringRedisTemplate中使用JSON序列化时泛型信息丢失的问题及其提出三种解决方案,可以根据性... 目录背景解决方案方案一方案二方案三总结背景在使用RedisTemplate操作redis时我们针对