1、某进程1执行 SETNX lock 以尝试获取锁

2、由于某进程2已获得了锁,所以进程1执行 SETNX lock 返回0,即获取锁失败

3、进程1执行 GET lock 来检测锁是否已超时,如果没超时,则线程等待一段时间,再次检测

4、如果进程1检测到锁已超时,即当前的时间大于键 lock 的值,进程1会执行以下操作

GETSET lock <current Unix timestamp + lock timeout + 1>

5、由于 GETSET 操作在设置键的值的同时,还会返回键的旧值,通过比较键 lock 的旧值是否小于当前时间,可以判断进程是否已获得锁

6、假如另一个进程3也检测到锁已超时,并在进程1之前执行了 GETSET 操作,那么进程1的 GETSET 操作返回的是一个大于当前时间的时间戳,这样进程1就不会获得锁而继续等待。注意到,即使进程1接下来将键 lock 的值设置了比进程3设置的更大的值也没影响。

另外,值得注意的是,在进程释放锁,即执行 DEL lock 操作前,需要先判断锁是否已超时。如果锁已超时,那么锁可能已由其他进程获得,这时直接执行 DEL lock 操作会导致把其他进程已获得的锁释放掉。

C# Code

using System;
using System.Threading;
using System.Threading.Tasks;
using CSRedis; namespace RedisLockDemo
{
public class CsRedisLock
{
private static readonly int _lock_timeout = 40;
private static readonly string _lock_key = "lock";
public static void Test()
{
var rds = new CSRedisClient("127.0.0.1:6379,password=123456,defaultDatabase=13,poolsize=50,ssl=false");
RedisHelper.Initialization(rds); Parallel.For(0, 13, x =>
{
if (GetLock(_lock_key))
{
Console.WriteLine($"person:{x},线程ID:{Thread.CurrentThread.ManagedThreadId},获得锁 woking"); if (DateTimeOffset.Now.ToUnixTimeMilliseconds() < RedisHelper.Get<long>(_lock_key))
{
//释放锁
RedisHelper.Del(_lock_key);
}
}
else
{
Console.WriteLine($"person:{x},线程ID:{Thread.CurrentThread.ManagedThreadId},获取锁异常");
}
});
Console.WriteLine();
} private static bool GetLock(string key)
{
bool getLocked = false;
try
{
while (!getLocked)
{
var now = DateTimeOffset.Now.ToUnixTimeMilliseconds();
var lock_time = now + _lock_timeout + 1;
getLocked = RedisHelper.SetNx(key, lock_time);
//判断是否获取锁,
if (getLocked || now > RedisHelper.Get<long>(key) && now > RedisHelper.GetSet<long>(key, lock_time))
{
getLocked = true;
}
else
{
Thread.Sleep(30);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return getLocked;
}
}
}

相关文档:https://redis.io/commands/setnx

Redis SETNX实现分布式锁的更多相关文章

  1. Redis setNX 实现分布式锁(重复数据插入可用其来实现排他锁)

    使用Redis的 SETNX 命令可以实现分布式锁,下文介绍其实现方法. SETNX命令简介 命令格式 SETNX key value 将 key 的值设为 value,当且仅当 key 不存在. 若 ...

  2. 基于redis实现的分布式锁

    基于redis实现的分布式锁 我们知道,在多线程环境中,锁是实现共享资源互斥访问的重要机制,以保证任何时刻只有一个线程在访问共享资源.锁的基本原理是:用一个状态值表示锁,对锁的占用和释放通过状态值来标 ...

  3. 一个Redis实现的分布式锁

    import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.conne ...

  4. 基于Redis的简单分布式锁的原理

    参考资料:https://redis.io/commands/setnx 加锁是为了解决多线程的资源共享问题.Java中,单机环境的锁可以用synchronized和Lock,其他语言也都应该有自己的 ...

  5. 在redis上实现分布式锁

    /** *在redis上实现分布式锁 */ class RedisLock { private $redisString; private $lockedNames = []; public func ...

  6. redis系列:分布式锁

    redis系列:分布式锁 1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分 ...

  7. Redis如何实现分布式锁

    今天我们来聊一聊分布式锁的那些事. 相信大家对锁已经不陌生了,我们在多线程环境中,如果需要对同一个资源进行操作,为了避免数据不一致,我们需要在操作共享资源之前进行加锁操作.在计算机科学中,锁(lock ...

  8. Redis高并发分布式锁详解

    为什么需要分布式锁 1.为了解决Java共享内存模型带来的线程安全问题,我们可以通过加锁来保证资源访问的单一,如JVM内置锁synchronized,类级别的锁ReentrantLock. 2.但是随 ...

  9. redis客户端、分布式锁及数据一致性

    Redis Java客户端有很多的开源产品比如Redission.Jedis.lettuce等. Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持:Redis ...

随机推荐

  1. getchar 和EOF

    本文章基于:http://www.cnblogs.com/QLinux/articles/2465329.html,稍作了修改. 大师级经典的著作,要字斟句酌的去读,去理解.以前在看K&R的T ...

  2. jQuery Cookie (内附 上百行的中文使用手册,与 所有的注释中文翻译)

    jQuery Cookie (内附 上百行的中文使用手册,与 所有的注释中文翻译) 博主亲自翻译. 大家多多捧场. 更多资源请点击"查看TA 的资源" .全场通通 2积分. htt ...

  3. OpenFOAM中的热传导?【翻译】

    翻译自:CFD-online 帖子地址:http://www.cfd-online.com/Forums/openfoam/70758-conductive-heat-transfer-openfoa ...

  4. vue-cli构建路径加载资源出错问题

    这份文档是对应 @vue/cli 3.x 版本的,官方文档https://cli.vuejs.org/zh/guide/ 项目打包执行npm run build的时候,打开dist目录的index.h ...

  5. 微信小程序 wxParse插件显示视频

    修改wxParse/html2json.js 文件 ,在 html2json(html, bindName) 方法里 var node = { node: 'element', tag: tag, } ...

  6. 2018-2019-2 网络对抗技术 20165311 Exp 8 Web基础

    2018-2019-2 网络对抗技术 20165311 Exp 8 Web基础 基础问题回答 实践过程记录 1.Web前端:HTML 2.Web前端:javascipt 3.Web后端:MySQL基础 ...

  7. C语言--输入输出格式

    一.PTA实验作业 题目1:7-3 温度转换 本题要求编写程序,计算华氏温度150°F对应的摄氏温度.计算公式:C=5×(F−32)/9,式中:C表示摄氏温度,F表示华氏温度,输出数据要求为整型. 1 ...

  8. 安卓APP在线升级

    安卓APP在线升级 通过IDHTTP组件在线下载APP到手机中,然后自动安装这个APP程序. 1)在线下载APP程序 需引用单元: {$IFDEF ANDROID} FMX.Helpers.Andro ...

  9. centos6.6 ftp 配置 修改默认端口等

    常规下21端口容易遭到别人的扫描.带来了一定程度的不安全.所以,最好的就是把21端口修改掉. 默认修改为6069 一.修改vsftp的配置文件 vi /etc/vsftpd/vsftpd.conf 在 ...

  10. [C#]加密解密 MD5、AES

    /// <summary> /// MD5函数 /// </summary> /// <param name="str">原始字符串</p ...