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. Go开发环境安装与环境变量配置

    1.Go安装包下载 https://studygolang.com/dl 2.安装 Windows平台下,直接下一步即可完成安装. 3.配置环境变量 系统变量 安装完成后,在系统变量的Path一栏,会 ...

  2. zabbix(7)邮件报警配置

    邮件报警可以使用Linux自带邮件服务器(postfix等),也可以使用其他邮件服务器(像腾讯邮箱,126邮箱) 一.使用mail. 1.确定zabbix server是否安装发送邮件的命令mail, ...

  3. Tkinter 之ScrollBar滚动条标签

    一.参数说明 参数 作用 background (bg) 设置背景颜色 borderwidth (bd) 指定边框宽度,通常是 2 像素 cursor  指定当鼠标在上方飘过的时候的鼠标样式 orie ...

  4. [Codeforces1148C]Crazy Diamond——构造

    题目链接: [Codeforces1148C]Crazy Diamond 题目大意: 给出一个$1\sim n$的排列要求将其排序,每次能交换两个位置的数当且仅当这两个位置下标差的绝对值大于等于$\f ...

  5. Java 学习资料网站集合

    一.开源项目的搜集 https://www.jianshu.com/p/6c75174e0f07 -- https://github.com/flyleft/tip 二.简单的开源项目 https:/ ...

  6. Flask上下文源码分析(一)

    flask中的上下文分两种,application context和request context,即应用上下文和请求上下文.   从名字上看,可能会有误解,认为应用上下文是一个应用的全局变量,所有请 ...

  7. spring aop中aspect和advisor的区别

    之前看到spring AOP配置aspect(切面)有两种方式,一种是利用注解的方式配置,一种是利用XML的方式配置. 我们的配置是这样的<aop:aspect>,还有另外一种<ao ...

  8. linux物理内存与虚拟内存

    http://www.360doc.com/content/14/0123/14/14450281_347336709.shtml 1.查看内存占用情况 $ free -m -h total used ...

  9. pom.xml中properties作用

    可以在properties下声明相应的版本信息,然后在dependency下引用的时候用${spring-version}就可以引入该版本jar包了 <properties> <sp ...

  10. android studio: 9:57 Unsupported Modules Detected: Compilation is not supported for following modules: map, app, ota, MediaEditor, rcLcmSercive, DroneSDK, qrcodelibrary, rcService, speechService. Unfo

    Android studio Error “Unsupported Modules Detected: Compilation is not supported for following modul ...