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 ...
随机推荐
- H-Fashion in Berland
#include <bits/stdc++.h> using namespace std; int a[1005]; int main() { int n; scanf("%d& ...
- 全国行政区域代码(免费来拿) xls格式 可直接导入
全部区域代码 地址:https://pan.baidu.com/s/1Elz-zW_nLS8YR8GZAn3WRw 提取码:ze3s
- 页面tr和td的的隐藏与显示
<view:qrytr attributes="class=zcrzs"> </view:qrytr> var bd11 = $("tr[ ...
- CodeForces - 1183E Subsequences (easy version) (字符串bfs)
The only difference between the easy and the hard versions is constraints. A subsequence is a string ...
- CORTEX-M3中断的现场保护问题
在<Cortex-M3 Devices Generic User Guide.pdf>中介绍了异常入栈和出栈的情况,详见2.3 Exception model.Cortex-M3内核的寄存 ...
- keras 在train_on_batch中启用tensorboard
def write_log(callback, names, logs, batch_no): for name, value in zip(names, logs): summary = tf.Su ...
- SurfaceView动态背景效果实现
package com.loaderman.customviewdemo; import android.content.Context; import android.graphics.*; imp ...
- 【集成模型】Stacking
0 - 思路 Stacking是许多集成方法的综合.其主要思路如下图所示,通过训练数据训练多个base learners(the first-level learners),这些learners的输出 ...
- spark "main" java.lang.ArrayIndexOutOfBoundsException: 10582
升级 你的 paranamer 到2.8 ,这是由于你的jdk版本1.8导致 <!-- https://mvnrepository.com/artifact/com.thoughtworks.p ...
- java读取request中的xml
java读取request中的xml 答: // 读取xml InputStream inputStream; StringBuffer sb = new StringBuffer(); inpu ...