網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
redis常見的加鎖命令分別是INCR、SETNX、SET
1 INCR
這種鎖的加鎖思路是:key不存在,那么key的值會(huì)先被初始化為0,然后再執(zhí)行INCR操作進(jìn)行加一。然后其它用戶在執(zhí)行INCR操作進(jìn)行加一時(shí),如果返回的數(shù)值大于1,說(shuō)明這個(gè)key正在被鎖定使用。
1、 客戶端A請(qǐng)求服務(wù)器獲取key的值為1表示獲取了鎖
2、 客戶端B也去請(qǐng)求服務(wù)器獲取key的值為2表示獲取鎖失敗
3、 客戶端A執(zhí)行代碼完成,刪除鎖
4、 客戶端B在等待一段時(shí)間后在去請(qǐng)求的時(shí)候獲取key的值為1表示獲取鎖成功
5、 客戶端B執(zhí)行代碼完成,刪除鎖
$redis->incr($key);
$redis->expire($key, $ttl); //設(shè)置生成時(shí)間為1秒
具體使用命令:
127.0.0.1:6379>INCR keyName
2 SETNX
這種加鎖的思路是,如果key不存在,將key設(shè)置為value,如果key存在,則SETNX不做任何動(dòng)作。
SETNX是SET if Not eXists的縮寫。
1、 客戶端A請(qǐng)求服務(wù)器設(shè)置key的值,如果設(shè)置成功就表示加鎖成功
2、 客戶端B也去請(qǐng)求服務(wù)器設(shè)置key的值,如果返回失敗,那么就代表加鎖失敗
3、 客戶端A執(zhí)行代碼完成,刪除鎖
4、 客戶端B在等待一段時(shí)間后在去請(qǐng)求設(shè)置key的值,設(shè)置成功
5、 客戶端B執(zhí)行代碼完成,刪除鎖
$redis->setNX($key, $value);
$redis->expire($key, $ttl);
具體使用命令:
redis> SETNX keyName value
(integer) 1
設(shè)置成功,返回1;設(shè)置失敗,返回0
3 SET
上面兩種方法都有一個(gè)問題,會(huì)發(fā)現(xiàn),都需要設(shè)置 key 過(guò)期。那么為什么要設(shè)置key過(guò)期呢?如果請(qǐng)求執(zhí)行因?yàn)槟承┰蛞馔馔顺隽耍瑢?dǎo)致創(chuàng)建了鎖但是沒有刪除鎖,那么這個(gè)鎖將一直存在,以至于以后緩存再也得不到更新。于是乎我們需要給鎖加一個(gè)過(guò)期時(shí)間以防不測(cè)。
但是借助 Expire 來(lái)設(shè)置就不是原子性操作了。所以還可以通過(guò)事務(wù)來(lái)確保原子性,但是還是有些問題,所以官方就引用了另外一個(gè),使用 SET 命令本身已經(jīng)從版本 2.6.12 開始包含了設(shè)置過(guò)期時(shí)間的功能。
1、 客戶端A請(qǐng)求服務(wù)器設(shè)置key的值,如果設(shè)置成功就表示加鎖成功
2、 客戶端B也去請(qǐng)求服務(wù)器設(shè)置key的值,如果返回失敗,那么就代表加鎖失敗
3、 客戶端A執(zhí)行代碼完成,刪除鎖
4、 客戶端B在等待一段時(shí)間后在去請(qǐng)求設(shè)置key的值,設(shè)置成功
5、 客戶端B執(zhí)行代碼完成,刪除鎖
$redis->set($key, $value, array('nx', 'ex' => $ttl)); //ex表示秒
具體使用:
redis>set key value NX EX max-lock-time 實(shí)現(xiàn)加鎖
命令解釋:
- key:key就是redis的key值作為鎖的標(biāo)識(shí),value在這里作為客戶端的標(biāo)識(shí),只有key-value都比配才有刪?除鎖的權(quán)利【保證安全性】
- max-lock-time:通過(guò)max-lock-time設(shè)置過(guò)期時(shí)間保證不會(huì)出現(xiàn)死鎖【避免死鎖】
- NX:只有這個(gè)key不存才的時(shí)候才會(huì)進(jìn)行操作,if not exists;
- EX:設(shè)置key的過(guò)期時(shí)間為秒,具體時(shí)間由第5個(gè)參數(shù)決定
加鎖代碼:?
Jedis jedis = new Jedis("127.0.0.1", 6379);
private static final String SUCCESS = "OK";
/**
* 加鎖操作
* @param key 鎖標(biāo)識(shí)
* @param value 客戶端標(biāo)識(shí)
* @param timeOut 過(guò)期時(shí)間
*/
public Boolean lock(String key,String value,Long timeOut){
String var1 = jedis.set(key,value,"NX","EX",timeOut);
if(LOCK_SUCCESS.equals(var1)){
return true;
}
return false;
}
解鎖代碼:
Jedis jedis = new Jedis("127.0.0.1", 6379);
private static final Long UNLOCK_SUCCESS = 1L;
/**
* 解鎖操作
* @param key 鎖標(biāo)識(shí)
* @param value 客戶端標(biāo)識(shí)
* @return
*/
public static Boolean unLock(String key,String value){
String luaScript = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then return
redis.call(\"del\",KEYS[1]) else return 0 end";
Object var2 = jedis.eval(luaScript,Collections.singletonList(key), Collections.singletonList(value));
if (UNLOCK_SUCCESS == var2) {
return true;
}
return false;
}
luaScript 這個(gè)字符串是個(gè)lua腳本,代表的意思是如果根據(jù)key拿到的value跟傳入的value相同就執(zhí)行del,否則就返回0【保證安全性】
jedis.eval(String,list,list);這個(gè)命令就是去執(zhí)行l(wèi)ua腳本,KEYS的集合就是第二個(gè)參數(shù),ARGV的集合就是第三參數(shù)【保證解鎖的原子操作】
上述就實(shí)現(xiàn)了怎么使用redis去正確的實(shí)現(xiàn)分布式鎖,但是有個(gè)小缺陷就是鎖過(guò)期時(shí)間要設(shè)置為多少合適,這個(gè)其實(shí)還是需要去根據(jù)業(yè)務(wù)場(chǎng)景考量一下的。
原文鏈接:https://blog.csdn.net/weixin_43119856/article/details/127721561
相關(guān)推薦
- 2023-02-02 python保留兩位小數(shù)的3種方法實(shí)例_python
- 2022-04-28 教你如何在Centos8-stream安裝PostgreSQL13_PostgreSQL
- 2022-06-13 CentOS7.6系統(tǒng)下Docker安裝部署教程_docker
- 2022-10-23 Kubernetes?k8s?configmap?容器技術(shù)解析_云其它
- 2022-05-01 Python類的定義和使用詳情_python
- 2022-10-11 CFS 調(diào)度器的vruntime
- 2022-07-16 TritonObjDet新增要素的方法
- 2022-07-18 SQL?Server中日期時(shí)間函數(shù)的用法詳解_MsSql
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支