小編給大家分享一下redis中分布式鎖的實(shí)現(xiàn)方法,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
成都創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供金川網(wǎng)站建設(shè)、金川做網(wǎng)站、金川網(wǎng)站設(shè)計、金川網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計與制作、金川企業(yè)網(wǎng)站模板建站服務(wù),10年金川做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價值的思路和整體網(wǎng)絡(luò)服務(wù)。
redis分布式鎖:
1、實(shí)現(xiàn)原理
利用redis中的set命令來實(shí)現(xiàn)分布式鎖。
從Redis 2.6.12版本開始,set可以使用下列參數(shù):
SET KEY VALUE [EX seconds] [PX milliseconds] [NX|XX]
EX second :設(shè)置鍵的過期時間為second秒。 SET key value EX second效果等同于SETEX key second value 。
PX millisecond :設(shè)置鍵的過期時間為millisecond毫秒。 SET key value PX millisecond效果等同于PSETEX key millisecond value 。
NX :只在鍵不存在時,才對鍵進(jìn)行設(shè)置操作。 SET key value NX效果等同于SETNX key value 。
XX :只在鍵已經(jīng)存在時,才對鍵進(jìn)行設(shè)置操作。
返回值:
SET 在設(shè)置操作成功完成時,才返回OK 。
如果設(shè)置了NX或者XX ,但因?yàn)闂l件沒達(dá)到而造成設(shè)置操作未執(zhí)行,那么命令返回空批量回復(fù)(NULL Bulk Reply)。
命令:
> SET key value EX ttl NX
大致思想是:
(a)SET lock currentTime+expireTime EX 600 NX,使用set設(shè)置lock值,并設(shè)置過期時間為600秒,如果成功,則獲取鎖;
(b)獲取鎖后,如果該節(jié)點(diǎn)掉線,則到過期時間ock值自動失效;
(c)釋放鎖時,使用del刪除lock鍵值;
使用redis單機(jī)來做分布式鎖服務(wù),可能會出現(xiàn)單點(diǎn)問題,導(dǎo)致服務(wù)可用性差,因此在服務(wù)穩(wěn)定性要求高的場合,官方建議使用redis集群(例如5臺,成功請求鎖超過3臺就認(rèn)為獲取鎖),來實(shí)現(xiàn)redis分布式鎖。詳見RedLock。
2、優(yōu)點(diǎn)
性能高,redis可持久化,也能保證數(shù)據(jù)不易丟失;
redis集群方式提高穩(wěn)定性。
3、缺點(diǎn)
使用redis主從切換時可能丟失部分?jǐn)?shù)據(jù)。
4、開源實(shí)現(xiàn)
python版本的開源實(shí)現(xiàn):python-redis-lock。
redis分布式鎖的具體實(shí)現(xiàn)方式:
加鎖和解鎖的方式:
private static final String LOCK_SUCCESS = "OK"; private static final String SET_IF_NOT_EXIST = "NX"; private static final String SET_WITH_EXPIRE_TIME = "PX"; private static final Long RELEASE_SUCCESS = 1L; /** * 嘗試獲取分布式鎖 * @param lockKey 鎖 * @param requestId 請求標(biāo)識 * @param expireTime 超期時間 * @return 是否獲取成功 */ public Boolean tryGetDistributedLock(String lockKey, String requestId, int expireTime) { Jedis jedis = this.jedisPool.getResource(); String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime); if (LOCK_SUCCESS.equals(result)) { return true; } return false; } /** * 釋放分布式鎖 * @param lockKey 鎖 * @param requestId 請求標(biāo)識 * @return 是否釋放成功 */ public Boolean releaseDistributedLock(String lockKey, String requestId) { Jedis jedis = this.jedisPool.getResource(); String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId)); if (RELEASE_SUCCESS.equals(result)) { return true; } return false; }
2、具體的應(yīng)用
try{ String requestId = UUID.randomUUID().toString(); Boolean flag = tryGetDistributedLock(lock,requestId,1000); int n = 0; while(!flag){ //如果沒有獲取鎖,可以嘗試下一個lock,如果都沒有,則嘗試 n 次,退出 ... if(n++>5){ throw new Exception("嘗試獲取鎖失敗");} ... } if(!flag){ throw new Exception("嘗試獲取鎖失敗"); } }catch(){ }finally{ releaseDistributedLock(lock,requestId); }
以上是redis中分布式鎖的實(shí)現(xiàn)方法的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!