分布式锁-Redis方式实现

本文介绍如何使用Redis实现分布式锁,解决微服务环境下资源共享变量的同步问题。通过对比Redis与Zookeeper,选择Redis作为分布式锁解决方案。文章详细阐述了实现分布式锁需考虑的因素,包括锁的获取、释放及可重入性,并提供了具体代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用Redis实现分布式锁

  最近公司在做微服务的升级改造项目,因此之前在单机系统下的应用锁ReentrantLock 以及 java的关键字synchronized,就不再适合作为锁来实现共享变量的同步。因为他们只适用于一台jvm内部。
后经过对比redis和zookeeper实现分布式锁,公司决定采用redis来实现分布式。

实现分布式锁要考虑的问题

1、要能够实现锁的功能,保证在同一时间只能有一个线程在处理数据。
2、要考虑锁的释放问题,不能造成死锁。
3、根据业务场景,要考虑锁的可重入性,关于可重入锁和不可重入锁,大家可参考这篇文章可重入锁与不可重入锁

redis的配置代码

本文采用的是redis的cluster模式:3主3从模式。
public static JedisCluster cluster = null;
static {
Set hostAndPorts = new HashSet<>();
HostAndPort node7001 = new HostAndPort(“127.0.0.1”, 7001);
HostAndPort node7002 = new HostAndPort(“127.0.0.1”, 7002);
HostAndPort node7003 = new HostAndPort(“127.0.0.1”, 7003);
hostAndPorts.add(node7001);
hostAndPorts.add(node7002);
hostAndPorts.add(node7003);
cluster = new JedisCluster(hostAndPorts);
}

获取锁

本文在Redis中采用hash的数据结构存储,key为要所住的对象,有两个field,一个为current,代表当前持有锁的线程名称,一个lockCount,表示当前持有锁线程的加锁次数。

尝试获取锁,当前线程尝试获取锁,若当前锁未被其他线程持有,则直接获取锁。

大家都知道Redis的setNX原子操作的,setnx后,在调用expire命令为key设置过期时间。但是此方法有一个问题,若是在执行完setnx后程序崩溃了,则该锁可能变成死锁。

因此我们可以写一个lua脚本,因为redis在执行脚本命令的是时候,是在一个事务内执行完成的。
代码示例:
尝试获取锁
脚本说明:首先判断当前锁的线程是否为当前线程,若为,则直接返回1;设置当前持有锁的线程成功,则设置锁的过期时间,以及设置上锁次数为0;返回1.其他返回0.

尝试加锁

首先,先判断当前线程是否获取锁成功,获取成功,调用redis设置加锁次数。
lock

解锁

判断当前线程是否持有锁,若持有该锁,则加锁次数减一,若是加锁次数为0 ;则直接释放锁。
unlock

释放锁

若当前线程持有锁,则直接删除锁。
在这里插入图片描述

运行结果

运行结果

结束语

欢迎大家一起来讨论,本人是一个初学redis的菜鸟

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值