分布式锁实现思想

分布式锁用于多线程在不同服务器上的并发控制,确保同一时间只有一个线程执行特定操作。常见的实现方式包括基于数据库、缓存(如Redis)和Zookeeper。Redis实现中,可通过SETNX+EXPIRE保证原子性并设置锁超时,防止死锁,解锁时通过UUID判断并删除锁。

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

什么时候需要用到分布式锁?

需要对一个共享变量进行多线程访问时,为了保证在高并发的情况下,一个方法或者变量在同一时间内只能被一个线程执行。若是单机部署,我们可以用并发控制来保证。若是多机部署,多线程分布在不同的机器上,简单的并发控制已经不能满足要求,这时就需要用到分布式锁。

分布式锁的目的:

系统部署在多个服务器上时,当有多个客户端同时对某个变量进行操作,要保证变量更新的有序性和操作唯一性。
即:不能多个客户端同时对变量进行操作。

分布式锁的三种实现方式

1. 基于数据库实现分布式锁;MySQL…
在数据库中创建一个表,表中包含方法名等字段,在方法名字段上创建一个唯一索引,要想执行某个方法时,需要使用这个方法名向表中插入数据,成功插入则获取锁,执行完再删除对应 的行数据释放锁。
步骤:
① 创建一个表 method_lock(id, method_name, desc, ip, update_time)
② 多个进程同时执行某个方法,那么需要同时在method_lock中插入数据,因为method_lock 的 method_name做了唯一性约束,所以最终只能有一个进程能执行此方法。
③ 成功插入则获取锁,执行完成后删除对应的行数据释放锁。

基于数据库实现分布式锁的缺点:
① 因为这是基于数据库实现的,数据库的可用性和性能将直接影响分布式锁的可用性及性能,所以,数据库需要双机部署、数据同步、主备切换;
② 不具有可重入的特性
③ 没有锁失效机制。(redis就可以,是指锁失效时间)
④ 不具有锁阻塞特性

2. 基于缓存(Redis等)实现分布式锁;
3. 基于Zookeeper实现分布式锁;

(这里先记录基于缓存的分布式锁)

2. 基于缓存(Redis等)实现分布式锁

2.1、Redis要实现分布式锁,需要满足一下条件:

  • 互斥性:在任意时刻,只能有一个客户端能持有锁
  • 不能死锁:客户端在持有锁的期间崩溃而没有主动释放锁,也要保证其他客户端能加锁
  • 容错性:只要大部分的Redis节点正常运行,客户端就可以加锁和解锁。

2.1、使用命令介绍:

加锁:

方法一:SETNX + expire

(1)SETNX
SETNX key val:当且仅当key不存在时,set一个key为val的字符串,返回1;若key存在,则什么都不做,返回0。

  • val 要具有唯一性,客户端可以使用UUID.randomUUID().toString()方法生成,用来标识这把锁是属于哪个请求加的,在解锁的时候就可以有依据。

(2)expire
expire key timeout:为key设置一个超时时间,单位为second,超过这个时间锁会自动释放,避免死锁。

方法二:SET key value px milliseconds nx / set()函数,

设置‘NX’参数,过期时间参数

  • 替代 setnx + expire 需要分两次执行命令的方式,保证了原子性;

解锁

(3)delete
delete key:删除key
在使用Redis实现分布式锁的时候,主要就会使用到这三个命令。

2.2、实现思想:
(1)获取锁的时候,使用setnx加锁,并使用expire命令为锁添加一个超时时间,超过该时间则自动释放锁,锁的value值为一个随机生成的UUID,通过此在释放锁的时候进行判断。
(2)获取锁的时候还设置一个获取的超时时间,若超过这个时间则放弃获取锁。
(3)释放锁的时候,通过UUID判断是不是该锁,若是该锁,则执行delete进行锁释放。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值