分布式锁实现:Redis

『Redis系列』Redis分布式锁解锁案例 Redis分布式锁解锁案例 相关视频教程(来自动力节点):https://www.bilibili.com/video/BV1Uz4y1X72A 相关资料下载:http://www.bjpowernode.com/?csdn 1、解锁代码 还是先展示代码,再带大家慢慢解释为什么这样实现: public class RedisTool { private static final Long RELEASE_SUCCESS = 1L; /** * 释放分布式锁 ... 阅读详情
13467292-d7a6fcde08503cdf

前言

单机环境下我们可以通过JAVA的Synchronized和Lock来实现进程内部的锁,但是随着分布式应用和集群环境的出现,系统资源的竞争从单进程多线程的竞争变成了多进程的竞争,这时候就需要分布式锁来保证。

实现分布式锁现在主流的方式大致有以下三种

1. 基于数据库的索引和行锁

2. 基于Redis的单线程原子操作:setNX

3. 基于Zookeeper的临时有序节点

这篇文章我们用Redis来实现,会基于现有的各种锁实现来分析,最后分享Redission的锁源码分析来看下分布式锁的开源实现

复制代码

设计实现

加锁

一、 通过setNx和getSet来实现

这是现在网上大部分版本的实现方式,笔者之前项目里面用到分布式锁也是通过这样的方式实现

public boolean lock(Jedis jedis, String lockName, Integer expire) {

//返回是否设置成功

//setNx加锁

long now = System.currentTimeMillis();

boolean result = jedis.setnx(lockName, String.valueOf(now + expire * 1000)) == 1;

if (!result) {

//防止死锁的容错

String timestamp = jedis.get(lockName);

if (timestamp != null && Long.parseLong(timestamp) < now) {

//不通过del方法来删除锁。而是通过同步的getSet

String oldValue = jedis.getSet(lockName, String.valueOf(now + expire));

if (oldValue != null && oldValue.equals(timestamp)) {

result = true;

jedis.expire(lockName, expire);

}

}

}

if (result) {

jedis.expire(lockName, expire);

}

return result;

}

代码分析:

通过setNx命令老保证操作的原子性,获取到锁,并且把过期时间设置到value里面

通过expire方法设置过期时间,如果设置过期时间失败的话,再通过value的时间戳来和当前时间戳比较,防止出现死锁

通过getSet命令在发现锁过期未被释放的情况下,避免删除了在这个过程中有可能被其余的线程获取到了锁

存在问题

防止死锁的解决方案是通过系统当前时间决定的,不过线上服务器系统时间一般来说都是一致的,这个不算是严重的问题

锁过期的时候可能会有多个线程执行getSet命令,在竞争的情况下,会修改value的时间戳,理论上来说会有误差

锁无法具备客户端标识,在解锁的时候可能被其余的客户端删除同一个key

虽然有小问题,不过大体上来说这种分布式锁的实现方案基本上是符合要求的,能够做到锁的互斥和避免死锁

二、 通过Redis高版本的原子命令

jedis的set命令可以自带复杂参数,通过这些参数可以实现原子的分布式锁命令

jedis.set(lockName, "", "NX", "PX", expireTime);

复制代码

代码分析

redis的set命令可以携带复杂参数,第一个是锁的key,第二个是value,可以存放获取锁的客户端ID,通过这个校验是否当前客户端获取到了锁,第三个参数取值NX/XX,第四个参数 EX|PX,第五个就是时间

NX:如果不存在就设置这个key XX:如果存在就设置这个key

EX:单位为秒,PX:单位为毫秒

这个命令实质上就是把我们之前的setNx和expire命令合并成一个原子操作命令,不需要我们考虑set失败或者expire失败的情况

解锁

一、 通过Redis的del命令

public boolean unlock(Jedis jedis, String lockName) {

jedis.del(lockName);

return true;

}

代码分析

通过redis的del命令可以直接删除锁,可能会出现误删其他线程已经存在的锁的情况

二、 Redis的del检查

public static void unlock2(Jedis jedis, String lockKey, String requestId) {

// 判断加锁与解锁是不是同一个客户端

if (requestId.equals(jedis.get(lockKey))) {

// 若在此时,这把锁突然不是这个客户端的,则会误解锁

jedis.del(lockKey);

}

}

代码分析

新增了requestId客户端ID的判断,但由于不是原子操作,在多个进程下面的并发竞争情况下,无法保证安全

三、 Redis的LUA脚本

public static boolean unlock3(Jedis jedis, String lockKey, String requestId) {

String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(""));

if (1L == (long) result) {

return true;

}

return false;

}

代码分析

通过Lua脚本来保证操作的原子性,其实就是把之前的先判断再删除合并成一个原子性的脚本命令,逻辑就是,先通过get判断value是不是相等,若相等就删除,否则就直接return

Redission的分布式锁

Redission是redis官网推荐的一个redis客户端,除了基于redis的基础的CURD命令以外,重要的是就是Redission提供了方便好用的分布式锁API

复制代码

一、 基本用法

RedissonClient redissonClient = RedissonTool.getInstance();

RLock distribute_lock = redissonClient.getLock("distribute_lock");

try {

boolean result = distribute_lock.tryLock(3, 10, TimeUnit.SECONDS);

} catch (InterruptedException e) {

e.printStackTrace();

} finally {

if (distribute_lock.isLocked()) {

distribute_lock.unlock();

}

}

代码流程

通过redissonClient获取RLock实例

tryLock获取尝试获取锁,第一个是等待时间,第二个是锁的超时时间,第三个是时间单位

执行完业务逻辑后,最终释放锁

二、 具体实现

我们通过tryLock来分析redission分布式的实现,lock方法跟tryLock差不多,只不过没有最长等待时间的设置,会自旋循环等待锁的释放,直到获取锁为止

long time = unit.toMillis(waitTime);

long current = System.currentTimeMillis();

//获取当前线程ID,用于实现可重入锁

final long threadId = Thread.currentThread().getId();

//尝试获取锁

Long ttl = tryAcquire(leaseTime, unit, threadId);

// lock acquired

if (ttl == null) {

return true;

}

time -= (System.currentTimeMillis() - current);

if (time <= 0) {

//等待时间结束,返回获取失败

acquireFailed(threadId);

return false;

}

current = System.currentTimeMillis();

//订阅锁的队列,等待锁被其余线程释放后通知

final RFuture subscribeFuture = subscribe(threadId);

if (!await(subscribeFuture, time, TimeUnit.MILLISECONDS)) {

if (!subscribeFuture.cancel(false)) {

subscribeFuture.addListener(new FutureListener() {

@Override

public void operationComplete(Future future) throws Exception {

if (subscribeFuture.isSuccess()) {

unsubscribe(subscribeFuture, threadId);

}

}

});

}

acquireFailed(threadId);

return false;

}

try {

time -= (System.currentTimeMillis() - current);

if (time <= 0) {

acquireFailed(threadId);

return false;

}

while (true) {

long currentTime = System.currentTimeMillis();

ttl = tryAcquire(leaseTime, unit, threadId);

// lock acquired

if (ttl == null) {

return true;

}

time -= (System.currentTimeMillis() - currentTime);

if (time <= 0) {

acquireFailed(threadId);

return false;

}

// waiting for message,等待订阅的队列消息

currentTime = System.currentTimeMillis();

if (ttl >= 0 && ttl < time) {

getEntry(threadId).getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);

} else {

getEntry(threadId).getLatch().tryAcquire(time, TimeUnit.MILLISECONDS);

}

time -= (System.currentTimeMillis() - currentTime);

if (time <= 0) {

acquireFailed(threadId);

return false;

}

}

} finally {

unsubscribe(subscribeFuture, threadId);

}

代码分析

首先tryAcquire尝试获取锁,若返回ttl为null,说明获取到锁了

判断等待时间是否过期,如果过期,直接返回获取锁失败

通过Redis的Channel订阅监听队列,subscribe内部通过信号量semaphore,再通过await方法阻塞,内部其实是用CountDownLatch来实现阻塞,获取subscribe异步执行的结果,来保证订阅成功,再判断是否到了等待时间

再次尝试申请锁和等待时间的判断,循环阻塞在这里等待锁释放的消息RedissonLockEntry也维护了一个semaphore的信号量

无论是否释放锁,最终都要取消订阅这个队列消息

redission内部的getEntryName是客户端实例ID+锁名称来保证多个实例下的锁可重入

tryAcquire获取锁

redisssion获取锁的核心代码,内部其实是异步调用,但是用get方法阻塞了

private Long tryAcquire(long leaseTime, TimeUnit unit, long threadId) {

return get(tryAcquireAsync(leaseTime, unit, threadId));

}

private RFuture tryAcquireAsync(long leaseTime, TimeUnit unit, final long threadId) {

if (leaseTime != -1) {

return tryLockInnerAsync(leaseTime, unit, threadId, RedisCommands.EVAL_LONG);

}

RFuture ttlRemainingFuture = tryLockInnerAsync(LOCK_EXPIRATION_INTERVAL_SECONDS, TimeUnit.SECONDS, threadId, RedisCommands.EVAL_LONG);

ttlRemainingFuture.addListener(new FutureListener() {

@Override

public void operationComplete(Future future) throws Exception {

if (!future.isSuccess()) {

return;

}

Long ttlRemaining = future.getNow();

// lock acquired

if (ttlRemaining == null) {

scheduleExpirationRenewal(threadId);

}

}

});

return ttlRemainingFuture;

}

tryLockInnerAsync方法内部是基于Lua脚本来获取锁的

先判断KEYS[1](锁名称)对应的key是否存在,不存在获取到锁,hset设置key的value,pexpire设置过期时间,返回null表示获取到锁

存在的话,锁被占,hexists判断是否是当前线程的锁,若是的话,hincrby增加重入次数,重新设置过期时间,不是当前线程的锁,返回当前锁的过期时间

RFuture tryLockInnerAsync(long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand command) {

internalLockLeaseTime = unit.toMillis(leaseTime);

return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, command,

"if (redis.call('exists', KEYS[1]) == 0) then " +

"redis.call('hset', KEYS[1], ARGV[2], 1); " +

"redis.call('pexpire', KEYS[1], ARGV[1]); " +

"return nil; " +

"end; " +

"if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +

"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +

"redis.call('pexpire', KEYS[1], ARGV[1]); " +

"return nil; " +

"end; " +

"return redis.call('pttl', KEYS[1]);",

Collections.singletonList(getName()), internalLockLeaseTime, getLockName(threadId));

}

复制代码

Redission避免死锁的解决方案:

Redission为了避免锁未被释放,采用了一个特殊的解决方案,若未设置过期时间的话,redission默认的过期时间是30s,同时未避免锁在业务未处理完成之前被提前释放,Redisson在获取到锁且默认过期时间的时候,会在当前客户端内部启动一个定时任务,每隔internalLockLeaseTime/3的时间去刷新key的过期时间,这样既避免了锁提前释放,同时如果客户端宕机的话,这个锁最多存活30s的时间就会自动释放(刷新过期时间的定时任务进程也宕机)

// lock acquired,获取到锁的时候设置定期更新时间的任务

if (ttlRemaining) {

scheduleExpirationRenewal(threadId);

}

//expirationRenewalMap的并发安全MAP记录设置过的缓存,避免并发情况下重复设置任务,internalLockLeaseTime / 3的时间后重新设置过期时间

private void scheduleExpirationRenewal(final long threadId) {

if (expirationRenewalMap.containsKey(getEntryName())) {

return;

}

Timeout task = commandExecutor.getConnectionManager().newTimeout(new TimerTask() {

@Override

public void run(Timeout timeout) throws Exception {

RFuture future = commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,

"if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +

"redis.call('pexpire', KEYS[1], ARGV[1]); " +

"return 1; " +

"end; " +

"return 0;",

Collections.singletonList(getName()), internalLockLeaseTime, getLockName(threadId));

future.addListener(new FutureListener() {

@Override

public void operationComplete(Future future) throws Exception {

expirationRenewalMap.remove(getEntryName());

if (!future.isSuccess()) {

log.error("Can't update lock " + getName() + " expiration", future.cause());

return;

}

if (future.getNow()) {

// reschedule itself

scheduleExpirationRenewal(threadId);

}

}

});

}

}, internalLockLeaseTime / 3, TimeUnit.MILLISECONDS);

if (expirationRenewalMap.putIfAbsent(getEntryName(), task) != null) {

task.cancel();

}

}

unlock解锁

protected RFuture unlockInnerAsync(long threadId) {

return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,

"if (redis.call('exists', KEYS[1]) == 0) then " +

"redis.call('publish', KEYS[2], ARGV[1]); " +

"return 1; " +

"end;" +

"if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then " +

"return nil;" +

"end; " +

"local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); " +

"if (counter > 0) then " +

"redis.call('pexpire', KEYS[1], ARGV[2]); " +

"return 0; " +

"else " +

"redis.call('del', KEYS[1]); " +

"redis.call('publish', KEYS[2], ARGV[1]); " +

"return 1; "+

"end; " +

"return nil;",

Arrays.asList(getName(), getChannelName()), LockPubSub.unlockMessage, internalLockLeaseTime, getLockName(threadId));

}

Redission的unlock解锁也是基于Lua脚本实现的,内部逻辑是先判断锁是否存在,不存在说明已经被释放了,发布锁释放消息后返回,锁存在再判断当前线程是否锁拥有者,不是的话,无权释放返回,解锁的话,会减去重入的次数,重新更新过期时间,若重入数捡完,删除当前key,发布锁释放消息

如果你现在在JAVA这条路上挣扎,也想在IT行业拿高薪,可以参加我们的训

练营课程,选择最适合自己的课程学习,技术大牛亲授,7个月后,进入名

企拿高薪。我们的课程内容有:Java工程化、高性能及分布式、高性能、高

架构、性能调优、Spring,MyBatis,Netty源码分析和大数据等多个知识点

。如果你想拿高薪的,想学习的,想就业前景好的,想跟别人竞争能取得优

势的,想进阿里面试但担心面试不过的,你都可以来,q群号为:835638062

注:加群要求

1、具有1-5工作经验的,面对目前流行的技术不知从何下手,需要突破技术

瓶颈的可以加。

2、在公司待久了,过得很安逸,但跳槽时面试碰壁。需要在短时间内进修

、跳槽拿高薪的可以加。

3、如果没有工作经验,但基础非常扎实,对java工作机制,常用设计思想

,常用java开发框架掌握熟练的,可以加。

4、觉得自己很牛B,一般需求都能搞定。但是所学的知识点没有系统化,很

难在技术领域继续突破的可以加。

5.阿里Java高级大牛直播讲解知识点,分享知识,多年工作经验的梳理和总

结,带着大家全面、科学地建立自己的技术体系和技术认知!

架构设计之分布式锁:分布式锁的由来、及Redis分布式锁的实现详解 在很多场景中,我们为了保证数据的最终一致性,需要很多的技术方案来支持,比如分布式事务、分布式锁等。那具体什么是分布式锁,分布式锁应用在哪些业务场景、如何来实现分布式锁呢?今天来探讨分布式锁这个话题。 什么是分布式锁 要介绍分布式锁,首先要提到与分布式锁相对应的是线程锁、进程锁。 1.线程锁 主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比如Synch.. 阅读详情

相关推荐

QMT量化交易桥接方案深度对比:从MiniQMT淘汰说起

量化交易系统中的API桥接,本质是解决本地终端与底层交易引擎之间的通信瓶颈。其核心原理在于绕过GUI封装、直连确定性执行层,从而获得低延迟、高可靠、可监控的指令通路。技术价值体现在策略实盘一致性提升、毫秒级响应保障及运维可控性增强。典型应用场景包括打板策略、T+0套利、高频网格等对时效与稳定性双敏感的自动化交易。本文聚焦国金证券QMT专业版生态,系统剖析DLL注入、HTTP反向代理、IPC共享内存与官方HTTP API四大桥接路径的性能边界、合规风险与工程落地成本,尤其深入解析qmt终端 client is

weixin_33892359的博客 457

Redis-Lua脚本详解

Redis中执行Lua脚本 SCRIPT LOAD 和 EVALSHA指令 错误处理函数pcall()与call() Script Kill 的原理

哆啦A梦 4128

如何从RHEL 8升级到RHEL 9

Red Hat 于 2022 年 5 月 17 日宣布全面推出 RHEL 9。这是 RHEL(Red Hat Enterprise Linux)的最新版本,它具有许多功能和增强功能。

u012748257的博客 1020

Redis(十一) 分布式锁

1

weixin_43189971的博客 938

python DEA: 基于非径向距离NDDF的Malmquist-Luenberger 指数及其分解

点赞发Nature 关注中Science Malmquist-Lenberger指数(ML指数)是距离函数与DEA计算中常用的指数,ML指数可以进一步分解为技术进步technological progress和效率改善effeciency change. 技术进步常被当做增长模型中的全要素生产率,用到许多计量经济研究中,探讨影响技术进步的环境变量。这里我分享一个考虑非期望产出下的NDDF方法计算ML指数。 该ML指数为global ML(区别于sequential ML) import numpy as

Cmmmmm丶的博客 5299

基于LangGraph的智能报告生成平台项目分析

不知道你是否知道或者了解OpenAI and Gemini Deep Research。他们是一种能够根据输入问题进行规划、结合网络搜索获取信息并最终呈现结果的研究工具或技术。那这样research是如何实现的呢?最近刚好看到一个实现类似功能的开源项目: open_deep_search。本文将基于该项目进行代码层面剖析。

u011160113的博客 924

【redis】原子性的实现--lua脚本

Lua 脚本可以将多条 Redis 命令写在一个脚本中。Redis 会将这个脚本作为一个整体执行,确保脚本内的所有命令是原子操作。脚本会检查 Redis 中的键是否等于传入的值,如果相等,则删除该键。

thorandloki的博客 630

【遥感数字图像处理(朱文泉)】第一章 数字图像基础

关于图像的定义、类型、模拟图像和数字图像

甜子yu的博客 4405

redis释放锁-lua脚本

分布式锁 redis释放锁-lua脚本

高艳艳的博客! 587

把对讲门铃(控制底楼铁门)接入米家服务器

今天讲个跟SDR或者无人机无关的东西,技术含量不高,但是方便了我的生活。 现在家门有智能锁,汽车也可以远程解锁发动,NFC门禁也可以用某些手机复制,唯独楼下的铁门,必须用老式对讲门铃控制。 也就是说其它钥匙都可以不带,就剩这个钥匙还必须随身携带。 另外有时候人不在家,不能开楼下铁门,快递员也没法把东西送上楼。 ......

老邵的开源世界 6551

【YOLOv12改进trick】高效多尺度卷积注意力EMCAD_Block模块引入YOLOv12,实现涨点和效率提升,含创新点Python代码

EMCAD引入YOLOv12模块,实现高效多尺度注意力模块引入到YOLOv12中的快速涨点及效率提升

向上生长的程序媛的博客 852

Redis系列教程(八):分布式锁的由来、及Redis分布式锁的实现详解

在很多场景中,我们为了保证数据的最终一致性,需要很多的技术方案来支持,比如分布式事务、分布式锁等。那具体什么是分布式锁,分布式锁应用在哪些业务场景、如何来实现分布式锁呢?今天来探讨分布式锁这个话题。 什么是分布式锁 要介绍分布式锁,首先要提到与分布式锁相对应的是线程锁、进程锁。 1.线程锁 主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比如Sy...

一个有情怀的程序猿博客 559

基于SVD矩阵分解的用户购物篮预测分析实战

基于SVD矩阵分解的用户购物篮预测分析实战

360

Redis系列:redis实现分布式锁

基于 Redis 实现一个通用的分布式锁组件。 整体模式 Jmeter发压到Nginx上,Nginx在负载到两台应用上,应用去redis上扣款,组成分布式环境。 注意在实验的时候,可以打包两个端口不同的jar包,也可以在idea上开启Allow parallel run达到实验目的。 SpringBoot jar启动报错:S

ljfirst的博客 3955

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

【Redis从入门到进阶】第 7 讲:基于 Redis 实现分布式锁

【Redis从入门到进阶】第 7 讲:基于 Redis 实现分布式锁

执梗的博客 4309

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Redis分布式锁:从原理到实现,一篇搞懂

Redis分布式锁通过SET NX PX命令实现跨服务的互斥机制,核心原理是利用Redis键的唯一性保证互斥。文章详细解析了分布式锁的三个关键问题:1) 锁过期与续命机制解决任务执行时间长的问题;2) 使用Lua脚本保证释放锁的原子性;3) Redis集群下的锁丢失问题及Redlock解决方案。最后给出了Java实现的完整流程,包括获取锁、锁续命和释放锁的标准操作,为分布式系统提供可靠的并发控制方案。

2301_80017072的博客 6350

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

分布式锁的几种实现方法:redis实现分布式锁

使用失效的方式实现分布式锁(推荐) import redis.clients.jedis.Jedis; /** * 使用redis实现分布式锁(推荐) * */ public class JedLock { private static final String LOCK_KEY = "jedis_lock"; private static final in...

dianqi0560的博客 161

Redlock:Redis分布式锁最牛逼的实现

普通实现 说道Redis分布式锁大部分人都会想到:setnx+lua,或者知道set key value px milliseconds nx。后一种方式的核心实现命令如下: - 获取锁(unique_value可以是UUID等) SET resource_name unique_value NX PX 30000 - 释放锁(lua脚本中,一定要比较value,防止误解锁) ...

weixin_30394333的博客 336

Redis 分布式锁实战:你一定听得懂的分布式锁实现方案

Redis 分布式锁的核心是基于原子操作保证互斥性,再通过过期时间、锁续约、集群部署等机制解决死锁、单点故障、锁提前释放等问题。手动实现分布式锁需兼顾诸多细节,容易出现漏洞,生产环境优先推荐使用 Redisson 框架,其封装了完整的特性,开箱即用,能大幅提升开发效率和系统稳定性。

RaLQNW8he的博客 413

分布式锁:如何使用Redis实现分布式锁?分布式锁的实现方式有哪些?

1.背景介绍 分布式锁是一种在分布式系统中实现并发控制的方法,它允许多个进程或线程同时访问共享资源,以确保数据的一致性和完整性。在分布式系统中,多个节点可能会同时尝试访问同一个资源,这可能导致数据的不一致或竞争条件。为了解决这个问题,我们需要使用分布式锁。 在本文中,我们将讨论如何使用Redis实现分布式锁,以及分布式锁的实现方式有哪些。我们还将讨论如何在实际应用场景中使用分布式锁,以及如何选...

AI天才研究院 944

面试官:如何用 Redis 实现分布式锁?

如果锁的超时时间设置过长,会影响性能,如果设置的超时时间过短会保护不到共享资源。比如在有些场景中,一个线程 A 获取到了锁之后,由于业务代码执行时间可能比较长,导致超过了锁的超时时间,自动失效,注意 A 线程没执行完,后续线程 B 又意外的持有了锁,意味着可以操作共享资源,那么两个线程之间的共享资源就没办法进行保护了。锁变量的值需要能区分来自不同客户端的加锁操作,以免在释放锁时,出现误释放操作,所以,我们使用 SET 命令设置锁变量值时,每个客户端设置的值是一个唯一值,用于标识客户端;...

weixin_45985053的博客 366

《Redis 分布式锁:3 种实现方案优缺点对比》

方案优点缺点SETNX 命令- 简单易用<br>- 低资源消耗<br>- 兼容性好- 非原子操作,易死锁<br>- 竞争条件风险高<br>- 需手动超时管理SET 命令扩展- 原子操作,可靠性高<br>- 自动超时<br>- 性能较好- 时钟依赖问题<br>- 不支持高级特性<br>- 版本要求限制Redlock 算法- 高可用性<br>- 减少单点故障<br>- 适合高并发- 实现复杂<br>- 性能开销大<br>- 时钟同步问题。

2501_93894473的博客 1379

Redis分布式锁:原理、实现与最佳实践

Redis分布式锁是解决分布式系统并发控制的有效工具,通过合理使用Redis的原子操作和过期机制,可以实现高效、可靠的分布式锁。在实际应用中,应根据系统的需求和特点,选择合适的实现方式和最佳实践,确保系统的正确性和性能。对于要求极高可靠性的场景,可以考虑使用Redlock算法或其他分布式协调服务如ZooKeeper、etcd等。对于一般场景,使用Redisson等成熟的客户端库已经能够满足大多数需求。

exlink2012的专栏 1006

【Redis25】Redis进阶:分布式锁实现

Redis进阶:分布式锁实现锁这个概念,不知道大家掌握的怎么样。我是先通过 Java ,知道在编程语言中是如何使用锁的。一般 Java 的例子会是操作一个相同的文件,但其实我们知道,不管是文件,还是数据库中的一条数据,只要是多个进程或者线程共享的,需要共同操作的数据,都会因为异步读写而带来一些问题,这些问题最终的解决方案往往就是通过锁。MySQL 中,有表锁、行锁、读写锁、意向锁、间隙锁等等,而在...

硬核项目经理 825
上一篇: SpringBoot|第四章:日志管理
下一篇: 编辑 SpringBoot|第五章:多环境配置
普通网友
博客等级 码龄8年 55粉丝 197原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值