首页 > 数据库 >Redis分布式锁实现一直到Redis相关操作总结

Redis分布式锁实现一直到Redis相关操作总结

时间:2023-10-14 09:15:50浏览次数:38  
标签:总结 return name timeoutSeconds KEYS Redis ARGV 分布式

FreeRedis 实现源码

/// <summary>
/// 开启分布式锁,若超时返回null
/// </summary>
/// <param name="name">锁名称</param>
/// <param name="timeoutSeconds">超时(秒)</param>
/// <param name="autoDelay">自动延长锁超时时间,看门狗线程的超时时间为timeoutSeconds/2 , 在看门狗线程超时时间时自动延长锁的时间为timeoutSeconds。除非程序意外退出,否则永不超时。</param>
/// <returns></returns>
public LockController Lock(string name, int timeoutSeconds, bool autoDelay = true)
{
    name = $"RedisClientLock:{name}";
    var startTime = DateTime.Now;
    while (DateTime.Now.Subtract(startTime).TotalSeconds < timeoutSeconds)
    {
        var value = Guid.NewGuid().ToString();
        if (SetNx(name, value, timeoutSeconds) == true)
        {
            double refreshSeconds = (double)timeoutSeconds / 2.0;
            return new LockController(this, name, value, timeoutSeconds, refreshSeconds, autoDelay);
        }
        Thread.CurrentThread.Join(3);
    }
    return null;
}

使用SETNX命令可以将一个键值对设置到Redis中,但只有在该键不存在时才会设置成功

if (SetNx(name, value, timeoutSeconds) == true)
将锁对应的键设置为某个固定的值,如果设置成功则表示获取到了锁

然后进去看看具体类做了什么

延长锁


/// <summary>
/// 延长锁时间,锁在占用期内操作时返回true,若因锁超时被其他使用者占用则返回false
/// </summary>
/// <param name="milliseconds">延长的毫秒数</param>
/// <returns>成功/失败</returns>
public bool Delay(int milliseconds)
{
    var ret = _client.Eval(@"local gva = redis.call('GET', KEYS[1])
if gva == ARGV[1] then
local ttlva = redis.call('PTTL', KEYS[1])
redis.call('PEXPIRE', KEYS[1], ARGV[2] + ttlva)
return 1
end
return 0", new[] { _name }, _value, milliseconds)?.ToString() == "1";
    if (ret == false) _autoDelayTimer?.Dispose(); //未知情况,关闭定时器
    return ret;
}

中间一大段lua脚本,大意就是 Redis 中与 KEYS[1] 对应的键的值等于 ARGV[1] 时,设置该键的过期时间为 ARGV[2] + ttlva,并返回操作成功;否则返回操作失败

其中local ttlva = redis.call('PTTL', KEYS[1]) 调用 Redis 的 PTTL命令获取与 KEYS[1] 对应的键的剩余过期毫秒单位时间,并将其赋给变量 ttlva

执行成功返回true,失败是false,如果是false则代表未知情况

刷新锁


/// <summary>
/// 刷新锁时间,把key的ttl重新设置为milliseconds,锁在占用期内操作时返回true,若因锁超时被其他使用者占用则返回false
/// </summary>
/// <param name="milliseconds">刷新的毫秒数</param>
/// <returns>成功/失败</returns>
public bool Refresh(int milliseconds)
{
    var ret = _client.Eval(@"local gva = redis.call('GET', KEYS[1])
if gva == ARGV[1] then
redis.call('PEXPIRE', KEYS[1], ARGV[2])
return 1
end
return 0", new[] { _name }, _value, milliseconds)?.ToString() == "1";
    if (ret == false) _autoDelayTimer?.Dispose(); //未知情况,关闭定时器
    return ret;
}

当 Redis 中与 KEYS[1] 对应的键的值等于 ARGV[1] 时,设置该键的过期时间为 ARGV[2],并返回操作成功;否则返回操作失败,其他和上一个类似

释放锁


 /// <summary>
/// 释放分布式锁
/// </summary>
/// <returns>成功/失败</returns>
public bool Unlock()
{
    _autoDelayTimer?.Dispose();
    return _client.Eval(@"local gva = redis.call('GET', KEYS[1])
if gva == ARGV[1] then
redis.call('DEL', KEYS[1])
return 1
end
return 0", new[] { _name }, _value)?.ToString() == "1";
}

当 Redis 中与 KEYS[1] 对应的键的值等于 ARGV[1] 时,删除该键,并返回操作成功

标签:总结,return,name,timeoutSeconds,KEYS,Redis,ARGV,分布式
From: https://www.cnblogs.com/ncellit/p/17763643.html

相关文章

  • math库常用函数+产生随机数总结
    math库常用函数+产生随机数总结1.对x开平方doublesqrt(x);//返回值为double类型,输入的x类型随意,只要是数的类型2.求常数e的x次方doubleexp(x);//返回值为double类型,输入的x类型随意,只要是数的类型3.求x的y次方double pow(x,y);//注意计算机没有储存自然常数e,不能直接输......
  • 2023-2024 20231313《计算机基础与程序设计》第三周学习总结
    2023-202420231313《计算机基础与程序设计》第三周学习总结作业速达作业课程<班级的链接>2023-2024计算机基础与程序设计作业要求《计算机基础与程序设计》第二周学习总结要求作业内容计算机科学概论第2章,第3章《C语言程序设计》第2章并完成云班课测试作业......
  • 今日总结
    首先上午花费两小时完成了数据清洗和可视化的展示,在数据清洗过程中主要遇到两个问题,第一个问题是如何将ip地址转化为省份,我初步思路是通过现有的数据库加上javaApi封装一个自定义UDF函数,然后打成jar包导入至hive控制台就可以使用了,但是错误有很多,第一个就是需要和第三方库一并打包......
  • 洛谷4363总结
    什么叫做博弈论DP呢?这里也是双方采取最佳策略,但是与普通博弈论不同的是,这里问的不是先手必胜or必败,而是问的最优值因此称作博弈论DP那么这种DP也是像SG游戏一样,我们想出博弈图然后倒推同时这题也是轮廓线DP,具体见这篇题解那么为什么菲菲要max,牛牛要min呢?我们就考虑dp数组的......
  • 每日总结
    10.12从今天开始写总结,其实之前就想开始的,但是操作太复杂了,而且我也懒,不想开始。但是时间一长有些写过的题技巧和方法都忘了,还是写写吧。P7828[CCO2021]SwapSwapSorthttps://www.luogu.com.cn/problem/P7828 这题根号分治,对出现次数不大于S的数直接双指针暴力,对出现次数......
  • 10.13总结
    1.完成了课堂测试2.学习了关于maven项目编写UDF自定义函数,打包到hive中使用,用于清洗数据将hive上的数据表导出到linux的目录下,再导出到本机后导入可视化SQLspingboot创建工程将数据库中的数据进行echart显示......
  • 10/3~10/13总结
    最近老毛病又开始犯了。10/3之前几场考试感觉问题不大,可能10/1松懈下来了,毛病一直不好。以后考试写完要从头读一遍代码,写对拍,等到熟练度提上去时间就足够了。10/13考试总结T1简单题,线段树水过T2没思路,赛后明白是性质贪心题。T3大粪讨,明明写的100分,不用心,挂60,还是要再......
  • 8088/8086微处理器与总线学习笔记总结
    目录一、微处理器与总线1.微处理器的概述1.1运算器1.2控制器1.2.1指令控制1.2.2时序控制1.2.3操作控制二、8086/8088微处理器1.8086/8088CPU的指令特点1.1指令流水线1.2内存的分段管理技术1.3支持多处理器系统2.8088/8086的外部引脚及其功能3.8086/8088的功能结构3.1内部......
  • Linux第二次周总结
    第三章用户管理3.1用户/组概览Linux系统是多用户、多任务的分时操作系统,系统上每一个进程都有一个特定的文件,每个文件都被一个特定的用户所拥有。每个用户都属于一个用户组或者多个组,系统可以对一个用户组中的所有用户进行集中管理。3.1.1用户标识:UID与GIDLinux系统并不能......
  • 2023-2024-1 20231413 《计算机基础与程序设计》第三周学习总结
    班级:2023-2024-1-计算机基础与程序设计作业要求:2023-2024-1《计算机基础与程序设计》教学进程目标:自学教材:计算机科学概论第2、3章并完成云班课测试《C语言程序设计》第2章并完成云班课测试教材学习内容总结:了解了进制转换、图像/音频压缩,计算机数学的基础知识教材学习中的......