之前專案中使用redis鎖實現秒殺等一些併發業務,在這裡整理一下基於redis實現分布式鎖的簡單入門例項,記錄一下,便於以後檢視、學習。
springboot整合redisson分布式鎖:
1、簡介
在分布式系統中存在併發場景,為了解決這一問題,基於redis鎖一定程度可以解決這一問題,但是也有缺點,如死鎖等。。。,
分布式系統實現的時候要注意的幾個關鍵點:
1、鎖資訊必須是會過期超時的,不能讓乙個執行緒長期占有乙個鎖而導致死鎖;
2、同一時刻只能有乙個執行緒獲取到鎖。
主要實現鎖功能的redis命令:
setnx(key, value):「set if not exits」,若該key-value不存在,則成功加入快取並且返回1,否則返回0。
get(key):獲得key對應的value值,若不存在則返回nil。
getset(key, value):先獲取key對應的value值,若不存在則返回nil,然後將舊的value更新為新的value。
expire(key, seconds):設定key-value的有效期為seconds秒,避免死鎖
delete (key):刪除key
2、實現思路
a、加鎖
當執行乙個執行緒業務時,通過加鎖(獲取鎖)實現防止別的執行緒去執行它;
獲取鎖的時候,使用setnx加鎖,並使用expire命令為鎖新增乙個超時時間,超過該時間則自動釋放鎖,鎖的value值為乙個隨機生成的uuid,通過此在釋放鎖的時候進行判斷。
獲取鎖的時候還設定乙個獲取的超時時間,若超過這個時間則放棄獲取鎖。
b、釋放鎖
釋放鎖的時候,通過uuid判斷是不是該鎖,若是該鎖,則執行delete進行鎖釋放。
3、**實現
其實**實現大同小異,實現思想就是上面的思路。。。
/*** 實現 redis 加鎖、釋放鎖
*/public class distributedlock
/*** 加鎖
* * @param locaname
* 鎖的key
* @param acquiretimeout
* 獲取超時時間
* @param timeout
* 鎖的超時時間
* @return 鎖標識
*/public string lockwithtimeout(string locaname, long acquiretimeout, long timeout)
// 返回-1代表key沒有設定超時時間,為key設定乙個超時時間
if (conn.ttl(lockkey) == -1)
try catch (interruptedexception e)
}} catch (jedi***ception e) finally
}return retidentifier;
}/**
* 釋放鎖
* * @param lockname
* 鎖的key
* @param identifier
* 釋放鎖的標識
* @return
*/public boolean releaselock(string lockname, string identifier)
retflag = true;
}conn.unwatch();
break;
}} catch (jedi***ception e) finally
}return retflag;}}
4、測試案例
模擬線程併發業務。。。
執行緒服務
加鎖後執行測試: 20個子執行緒業務被順序執行
不加鎖後執行測試: 20個子執行緒業務被非順序執行,誰搶到資源誰先執行。。
基於Redis實現分布式鎖
分布式鎖的基本功能 1.同一時刻只能存在乙個鎖 2.需要解決意外死鎖問題,也就是鎖能超時自動釋放 3.支援主動釋放鎖 分布式鎖解決什麼問題 多程序併發執行任務時,需要保證任務的有序性或者唯一性 準備 redis版本 2.6 redis是主從 sentinel模式 為了高可用 原理 redis2.6之...
基於redis實現分布式鎖
實現方式 具備條件 確保鎖可用,必須要滿足一下幾個條件 1 互斥性,任意時刻只有乙個使用者能持有鎖 2 不會產生死鎖,假設某個使用者在持有鎖的期間由於服務崩潰或者其他原因沒有主動釋放鎖,也能保證後續其他使用者可以加鎖 3 加鎖和解鎖必須是同一使用者,b使用者無法解除a使用者加的鎖 實現 1 引入je...
基於redis實現分布式鎖
四個同時都去切換表 1 的操作是不可以的,他們要先從 redis 獲取一把鎖,沒有獲取到鎖的就直接退出,等待下一次定時任務的排程。拿到了鎖的就去執行切換當前分表的操作 獲取鎖 和 釋放鎖 的關鍵 如下所示 set the string value as value of the key.the st...