Redis实现分布式锁的7种方案 您所在的位置:网站首页 redis谁开发的 Redis实现分布式锁的7种方案

Redis实现分布式锁的7种方案

2023-07-19 14:40| 来源: 网络整理| 查看: 265

种方案前言

日常开发中,秒杀下单、抢红包等等业务场景,都需要用到分布式锁。而Redis非常适合作为分布式锁使用。本文将分七个方案展开,跟大家探讨Redis分布式锁的正确使用方式。如果有不正确的地方,欢迎大家指出哈,一起学习一起进步。

 

什么是分布式锁 方案一:SETNX + EXPIRE 方案二:SETNX + value值是(系统时间+过期时间) 方案三:使用Lua脚本(包含SETNX + EXPIRE两条指令) 方案四:SET的扩展命令(SET EX PX NX) 方案五:SET EX PX NX  + 校验唯一随机值,再释放锁 方案六: 开源框架~Redisson 方案七:多机实现的分布式锁Redlock 什么是分布式锁 ❝

分布式锁其实就是,控制分布式系统不同进程共同访问共享资源的一种锁的实现。如果不同的系统或同一个系统的不同主机之间共享了某个临界资源,往往需要互斥来防止彼此干扰,以保证一致性。

我们先来看下,一把靠谱的分布式锁应该有哪些特征:

图片 「互斥性」: 任意时刻,只有一个客户端能持有锁。 「锁超时释放」:持有锁超时,可以释放,防止不必要的资源浪费,也可以防止死锁。 「可重入性」:一个线程如果获取了锁之后,可以再次对其请求加锁。 「高性能和高可用」:加锁和解锁需要开销尽可能低,同时也要保证高可用,避免分布式锁失效。 「安全性」:锁只能被持有的客户端删除,不能被其他客户端删除 Redis分布式锁方案一:SETNX + EXPIRE

提到Redis的分布式锁,很多小伙伴马上就会想到setnx+ expire命令。即先用setnx来抢锁,如果抢到之后,再用expire给锁设置一个过期时间,防止锁忘记了释放。

SETNX 是SET IF NOT EXISTS的简写.日常命令格式是SETNX key value,如果 key不存在,则SETNX成功返回1,如果这个key已经存在了,则返回0。

假设某电商网站的某商品做秒杀活动,key可以设置为key_resource_id,value设置任意值,伪代码如下:

if(jedis.setnx(key_resource_id,lock_value) == 1){ //加锁    expire(key_resource_id,100); //设置过期时间    try {        do something  //业务请求    }catch(){  }  finally {       jedis.del(key_resource_id); //释放锁    }}

但是这个方案中,setnx和expire两个命令分开了,「不是原子操作」。如果执行完setnx加锁,正要执行expire设置过期时间时,进程crash或者要重启维护了,那么这个锁就“长生不老”了,「别的线程永远获取不到锁啦」。

Redis分布式锁方案二:SETNX + value值是(系统时间+过期时间)

为了解决方案一,「发生异常锁得不到释放的场景」,有小伙伴认为,可以把过期时间放到setnx的value值里面。如果加锁失败,再拿出value值校验一下即可。加锁代码如下:

long expires = System.currentTimeMillis() + expireTime; //系统时间+设置的过期时间String expiresStr = String.valueOf(expires);

// 如果当前锁不存在,返回加锁成功if (jedis.setnx(key_resource_id, expiresStr) == 1) {        return true;} // 如果锁已经存在,获取锁的过期时间String currentValueStr = jedis.get(key_resource_id);

// 如果获取到的过期时间,小于系统当前时间,表示已经过期if (currentValueStr != null && Long.parseLong(currentValueStr)  30ms+40ms+50ms+4m0s+50ms) 如果取到了锁,key的真正有效时间就变啦,需要减去获取锁所使用的时间。 如果获取锁失败(没有在至少N/2+1个master实例取到锁,有或者获取锁时间已经超过了有效时间),客户端要在所有的master节点上解锁(即便有些master节点根本就没有加锁成功,也需要解锁,以防止有些漏网之鱼)。 ❞

简化下步骤就是:

按顺序向5个master节点请求加锁 根据设置的超时时间来判断,是不是要跳过该master节点。 如果大于等于3个节点加锁成功,并且使用的时间小于锁的有效期,即可认定加锁成功啦。 如果获取锁失败,解锁!

Redisson实现了redLock版本的锁,有兴趣的小伙伴,可以去了解一下哈~

参考与感谢 redis系列:分布式锁[1] 浅析 Redis 分布式锁解决方案[2] 细说Redis分布式锁🔒[3] Redlock:Redis分布式锁最牛逼的实现 Reference [1]

redis系列:分布式锁:https://juejin.cn/post/6844903656911798285

[2]

浅析 Redis 分布式锁解决方案:https://www.infoq.cn/article/dvaaj71f4fbqsxmgvdce

[3]

细说Redis分布式锁🔒:https://juejin.cn/post/6844904082860146695#heading-3

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有