Redis实现安全分布式锁的方法技术

技术编号:36210073 阅读:13 留言:0更新日期:2023-01-04 12:06
本发明专利技术是Redis实现安全分布式锁的方法,包括:客户A向系统发起业务请求,后端创建线程A执行请求,通过业务对象某属性作为key,创建UUID作为value,设置超时时间获取锁;线程A开始执行业务,线程A处理时间超过超时时间;客户B也向系统发起相同业务请求,后端创建线程B执行请求,线程A持有锁已超时,线程B通过同样业务对象某属性作为key,创建UUID作为value,设置超时时间获取锁;线程A执行完毕,通过之前UUID释放锁,Redis中缓存UUID已改变,释放锁失败事务回滚;线程B执行完毕,通过线程B之前UUID释放锁,释放成功提交事务。本发明专利技术的优点:1)在大并发场景下通过原子性操作保证分布式锁的有效性;2)谁获取锁谁负责释放锁,保证了数据的一致性。数据的一致性。数据的一致性。

【技术实现步骤摘要】
Redis实现安全分布式锁的方法


[0001]本专利技术涉及的是Redis实现安全分布式锁的方法,属于分布式


技术介绍

[0002]在分布式领域,不同进程可能同时共同访问、操作某个共享资源,如果不加锁控制的话,会出现很多意想不到的结果,导致数据不一致。
[0003]例如像电商秒杀场景,同一时刻,大量请求进来,如果不加锁的话,会出现下单数量和库存数量不匹配的情况,导致无法发货,这个时候就需要使用分布式锁。
[0004]Redis是一款基于内存的key value缓存服务,是很合适用于分布式锁的实现的,加锁和解锁需要的开销成本极低,效率也非常高,还自带超时功能。基本原理是当某个线程需要操作某个领域的共享对象时,在Redis中set该对象的唯一属性作为key,然后设置该key的超时时间,这个线程操作完以后,通过释放key来达到释放锁的目的。
[0005]参照Redis官方文档,Redis现有实现分布式锁的方案一般都是SETNX(SET IF NOT EXISTS)+EXPIRE方式,即先用SETNX来抢锁,如果抢到之后,再用EXPIRE给锁设置一个过期时间,防止进程挂掉锁一直得不到释放,使用该方案的秒杀系统一种实施例如下图1所示,伪代码实现如下:
[0006][0007][0008]虽然使用上述方案也可以实现分布式锁,但是它有几个缺点,首先,SETNX和EXPIRE操作是分两步做的,不是一个原子性操作,如果某个进程SETNX操作后挂机了,那么这个锁将永远无法得到释放。其次,还有一个缺点,就是当A线程获取到锁后,执行时间超过了设置的超时时间,当B线程再来获取锁的时候,可以获取到锁,在B线程执行过程中,A线程执行完了,然后释放了锁,这时候B线程处在无锁的状态下,如图2所示,这个过程可能会导致数据的不一致。

技术实现思路

[0009]本专利技术提出的是Redis实现安全分布式锁的方法,其目的旨在克服现有技术存在的上述缺陷,保证分布式锁的有效性,保证数据的一致性。
[0010]本专利技术的技术解决方案:Redis实现安全分布式锁的方法,包括以下步骤:
[0011]步骤S1:当客户A开始向系统发起业务请求,后端创建线程A执行该请求,通过业务对象某个属性作为key,创建的UUID作为value,设置超时时间,获取锁;
[0012]步骤S2:线程A开始执行业务操作,因为某些原因线程A处理时间超过了设置的超时时间;
[0013]步骤S3:客户B此时也向系统发起相同的业务请求,后端创建线程B执行该请求,这时线程A持有的锁已经超时,线程B同样通过同样业务对象的某个属性作为key,创建的UUID作为value,设置超时时间,获取锁;
[0014]步骤S4:当线程A执行完毕后,通过之前生成的UUID来释放锁,发现Redis中的缓存的UUID已改变,释放锁失败,事务回滚;
[0015]步骤S5:线程B执行完毕后,通过线程B之前生成UUID来释放锁,释放成功,提交事务。
[0016]优选的,获取锁和设置超时时间是原子性的,获取锁时设置当前线程的唯一随机值,线程释放锁时,根据当前线程的唯一随机值来释放。
[0017]优选的,用Lua脚本来保证SETNX和EXPIRE的原子性。
[0018]优选的,用Redis的SET指令扩展参数,SET key value[EX seconds][PX milliseconds][NX|XX]来保证SETNX和EXPIRE的原子性。
[0019]优选的,为每个线程获得锁的时候生成一个随机值uuid,在删除的时候,进行校验,用Lua脚本合并判断逻辑与删除逻辑。
[0020]本专利技术的优点:1)在大并发场景下,例如电商秒杀,通过原子性操作,保证分布式锁的有效性;
[0021]2)谁获取锁,谁负责释放锁,保证了数据的一致性。
附图说明
[0022]图1是现有技术Redis实现分布式锁的方案的一种秒杀系统实施例示意图。
[0023]图2是现有技术Redis实现分布式锁的一种实施例流程图。
[0024]图3是本专利技术Redis实现安全分布式锁的一种实施例流程图。
具体实施方式
[0025]下面结合实施例和具体实施方式对本专利技术作进一步详细的说明。
[0026]为解决现有技术存在的上述问题,包含两个关键点,第一:保证SETNX和EXPIRE操作是一个原子操作;第二:保证一个原则,谁获得锁,谁有资格释放锁。
[0027]为保证以上第一个关键点,可以有两种解决方式,第一种是使用Lua脚本来保证SETNX和EXPIRE的原子性,Lua脚本伪代码如下:
[0028][0029]还有一种方式可以巧用Redis的SET指令扩展参数,SET key value[EX seconds][PX milliseconds][NX|XX],加锁伪代码如下:
[0030]jedis.set(key,lock_value,”NX”,”EX”,100s)
[0031]为保证以上第二个关键点,既然锁可能被别的线程误删,需要为每个线程获得锁的时候生成一个随机值uuid,在删除的时候,进行校验,伪代码如下:
[0032][0033]由于上述判断是否是当前线程加的锁和释放锁不是一个原子操作,如果调用jedis.del()释放锁的时候,可能这把锁已经不属于当前客户端,会接触他人加的锁,为了严谨起见,也要用Lua脚本代替,Lua脚本伪代码如下:
[0034][0035]通过给当前线程获取锁增加uuid随机值,加上Lua脚本合并判断逻辑与删除逻辑,
保证了只有获取锁的线程才能释放锁,从而不会释放其他线程加的锁,保证了数据的一致性。调整后流程的示意图如图3所示。
[0036]实施例
[0037]整体加锁流程步骤如下:
[0038]步骤S1:当客户A开始向系统发起秒杀商品的请求,后端创建线程A执行该请求,通过商品的某个属性作为key,创建的UUID作为value,设置超时时间,获取锁。
[0039]步骤S2:线程A开始执行业务操作,可能因为某些原因,线程A处理时间超过了设置的超时时间。
[0040]步骤S3:客户B这时也发起了秒杀同一个商品的请求,后端创建线程B执行该请求,这时线程A持有的锁已经超时,线程B同样通过商品的某个属性作为key,创建的UUID作为value,设置超时时间,获取锁。
[0041]步骤S4:当线程A执行完毕后,通过之前生成的UUID来释放锁,发现Redis中的缓存的UUID已经变了,释放锁失败,事务回滚。
[0042]步骤S5:线程B执行完毕后,通过线程B之前生成UUID来释放锁,释放成功,提交事务。
[0043]需要注意的是:
[0044]1)获取锁和设置超时时间必须是原子性的;
[0045]2)获取锁时,必须设置当前线程的唯一随机值;
[0046]3本文档来自技高网
...

【技术保护点】

【技术特征摘要】
1.Redis实现安全分布式锁的方法,其特征在于,包括以下步骤:步骤S1:当客户A开始向系统发起业务请求,后端创建线程A执行该请求,通过业务对象某个属性作为key,创建的UUID作为value,设置超时时间,获取锁;步骤S2:线程A开始执行业务操作,因为某些原因线程A处理时间超过了设置的超时时间;步骤S3:客户B此时也向系统发起相同的业务请求,后端创建线程B执行该请求,这时线程A持有的锁已经超时,线程B同样通过同样业务对象的某个属性作为key,创建的UUID作为value,设置超时时间,获取锁;步骤S4:当线程A执行完毕后,通过之前生成的UUID来释放锁,发现Redis中的缓存的UUID已改变,释放锁失败,事务回滚;步骤S5:线程B执行完毕后,通过线程B之前生成UUID来释放锁,释放成功,提交事务。2.如权利要求1所述的Redis实现安全分布...

【专利技术属性】
技术研发人员:崔瑾黄建杰
申请(专利权)人:央视国际网络无锡有限公司
类型:发明
国别省市:

网友询问留言 已有0条评论
  • 还没有人留言评论。发表了对其他浏览者有用的留言会获得科技券。

1