Redis SETNX实现分布式锁
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实现分布式锁的更多相关文章
- Redis setNX 实现分布式锁(重复数据插入可用其来实现排他锁)
使用Redis的 SETNX 命令可以实现分布式锁,下文介绍其实现方法. SETNX命令简介 命令格式 SETNX key value 将 key 的值设为 value,当且仅当 key 不存在. 若 ...
- 基于redis实现的分布式锁
基于redis实现的分布式锁 我们知道,在多线程环境中,锁是实现共享资源互斥访问的重要机制,以保证任何时刻只有一个线程在访问共享资源.锁的基本原理是:用一个状态值表示锁,对锁的占用和释放通过状态值来标 ...
- 一个Redis实现的分布式锁
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.conne ...
- 基于Redis的简单分布式锁的原理
参考资料:https://redis.io/commands/setnx 加锁是为了解决多线程的资源共享问题.Java中,单机环境的锁可以用synchronized和Lock,其他语言也都应该有自己的 ...
- 在redis上实现分布式锁
/** *在redis上实现分布式锁 */ class RedisLock { private $redisString; private $lockedNames = []; public func ...
- redis系列:分布式锁
redis系列:分布式锁 1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分 ...
- Redis如何实现分布式锁
今天我们来聊一聊分布式锁的那些事. 相信大家对锁已经不陌生了,我们在多线程环境中,如果需要对同一个资源进行操作,为了避免数据不一致,我们需要在操作共享资源之前进行加锁操作.在计算机科学中,锁(lock ...
- Redis高并发分布式锁详解
为什么需要分布式锁 1.为了解决Java共享内存模型带来的线程安全问题,我们可以通过加锁来保证资源访问的单一,如JVM内置锁synchronized,类级别的锁ReentrantLock. 2.但是随 ...
- redis客户端、分布式锁及数据一致性
Redis Java客户端有很多的开源产品比如Redission.Jedis.lettuce等. Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持:Redis ...
随机推荐
- dashucoding记录2019.6.8
WordPress网站 网址: https://cn.wordpress.org/ 阿里云市场 https://market.aliyun.com/products/53616009?spm=a2c4 ...
- K-D Tree学习笔记
用途 做各种二维三维四维偏序等等. 代替空间巨大的树套树. 数据较弱的时候水分. 思想 我们发现平衡树这种东西功能强大,然而只能做一维上的询问修改,显得美中不足. 于是我们尝试用平衡树的这种二叉树结构 ...
- gulp4配置多页面项目编译打包
又开始公司的新项目了... 那当我们拿到公司新项目的时候我们需要做些什么呢? 下面就来分享一下我的工作步骤吧(仅使用于初学者,大神勿见怪- -,有不好的地方希望指出,十分感谢) 1. 整版浏览 这是一 ...
- 1823:【00NOIP提高组】方格取数
#include<bits/stdc++.h> using namespace std; ][]; ][][][]; inline int max(int x,int y) { retur ...
- buoyantSimpleFoam求解器:恒热流壁面【翻译】
翻译自:CFD-online 帖子地址:http://www.cfd-online.com/Forums/openfoam-solving/148183-buoyantsimplefoam-fixed ...
- idea创建Web项目(基于Maven多模块)
简述:通常我们开发的项目结构是由多个modules项目组合而成,并且由有个parent的maven项目整体管理.废话少说,直接进入创建过程. 创建parent项目 1.打开idea工具,按照下图操作, ...
- MySQL_JDBC_jar包的下载与使用(Windows)
1. 下载 (1) 打开MySQL_JDBC的下载网站:https://dev.mysql.com/downloads/connector/j/ (2) 选择操作系统:Platform Indepen ...
- docker install and minikube install
1.选择国内的云服务商,这里选择阿里云为例 curl -sSL http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/ ...
- [RK3288] 外接USB设备出现丢数
CPU:RK3288 系统:Android 5.1 主板外接 USB 接口的外设,经常会出现丢数的现象,这种问题在很多 USB 接口的外设上都遇到过,例如:USB读卡器.USB扫描枪等 有一个共同点是 ...
- [Andorid] 通过JNI实现kernel与app进行spi通讯
CPU:RK3399 系统:Android 7.1 人脸识别的要求越来越高,因此主板增加了 SE 加密芯片,加密芯片通过 spi 接口与 CPU 通讯. 对于 kernel 层的代码,Linux 原始 ...