日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747


 

什么是分布式鎖,分布式鎖應用在哪些業務場景、如何來實現分布式鎖呢?今天來詳解redis分布式鎖的實現@mikechen

分布式鎖的由來

在開始講分布式鎖之前,有必要簡單介紹一下,為什么需要分布式鎖?

首先在傳統單機部署的情況下,可以使用JAVA并發處理相關的ReentrantLcok或Synchronized進行互斥控制,用于解決單機并發共享資源問題。

但是在分布式系統后,由于分布式系統是在多線程、多進程并且分布在不同機器上,這將使原單機并發控制鎖策略失效。

為了解決這個問題就需要一種跨JVM的互斥機制來控制共享資源的訪問,這就是分布式鎖的由來。

當多個進程不在同一個系統中,就需要用分布式鎖控制多個進程對資源的訪問。

分布式鎖的特點

首先,為了確保分布式鎖可用,我們至少要確保鎖的實現同時滿足以下四個條件:

1、互斥性:任意時刻,只能有一個客戶端獲取鎖,不能同時有兩個客戶端獲取到鎖;

2、安全性:鎖只能被持有該鎖的客戶端刪除,不能由其它客戶端刪除;

3、死鎖:獲取鎖的客戶端因為某些原因(如down機等)而未能釋放鎖,其它客戶端再也無法獲取到該鎖;

4、容錯:當部分節點(Redis節點等)down機時,客戶端仍然能夠獲取鎖和釋放鎖。

分布式鎖的具體實現


 

分布式鎖一般有三種實現方式:

1. 數據庫樂觀鎖;

2. 基于Zookeeper的分布式鎖;

3.基于Redis的分布式鎖;

這里推薦使用Redis分布式鎖的方案,下面我就重點詳解Redsi分布式鎖的實現。

Redis實現分布式鎖

1.Set語法

Redis實現分布式鎖,基于Redis Set命令。

Set語法如下:

SET key value [EX seconds] [PX milliseconds] [NX|XX]

下面我分別談談這幾個參數:

 

  • EX second :設置鍵的過期時間為 second 秒;
  • PX millisecond :設置鍵的過期時間為 millisecond 毫秒;
  • NX :只在鍵不存在時,才對鍵進行設置操作;
  • XX :只在鍵已經存在時,才對鍵進行設置操作。

 

2.加鎖

public class RedisTool { 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"; /** * 嘗試獲取分布式鎖 * @param jedis Redis客戶端 * @param lockKey 鎖 * @param requestId 請求標識 * @param expireTime 超期時間 * @return 是否獲取成功 */ public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) { String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);if (LOCK_SUCCESS.equals(result)) {return true;}return false;} }jedis.set(String key, String value, String nxxx, String expx, int time)

這個set()方法一共有五個形參:

第一個為key,我們使用key來當鎖,因為key是唯一的。

第二個為value,我們傳的是requestId,很多童鞋可能不明白,有key作為鎖不就夠了嗎,為什么還要用到value?原因就是我們在上面講到可靠性時,分布式鎖要滿足第四個條件解鈴還須系鈴人,通過給value賦值為requestId,我們就知道這把鎖是哪個請求加的了,在解鎖的時候就可以有依據。requestId可以使用UUID.randomUUID().toString()方法生成。

第三個為nxxx,這個參數我們填的是NX,意思是SET IF NOT EXIST,即當key不存在時,我們進行set操作;若key已經存在,則不做任何操作;

第四個為expx,這個參數我們傳的是PX,意思是我們要給這個key加一個過期的設置,具體時間由第五個參數決定。

第五個為time,與第四個參數相呼應,代表key的過期時間。

總的來說,執行上面的set()方法就只會導致兩種結果:1. 當前沒有鎖(key不存在),那么就進行加鎖操作,并對鎖設置個有效期,同時value表示加鎖的客戶端。2. 已有鎖存在,不做任何操作。

2.解鎖

public class RedisTool { private static final Long RELEASE_SUCCESS = 1L; /** * 釋放分布式鎖 * @param jedis Redis客戶端 * @param lockKey 鎖 * @param requestId 請求標識 * @return 是否釋放成功 */ public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) { 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;} }

那么這段Lua代碼的功能是什么呢?其實很簡單,首先獲取鎖對應的value值,檢查是否與requestId相等,如果相等則刪除鎖(解鎖)。

以上就是redis實現分布式鎖詳解,除此之外,也可以使用Redission(Redis 的客戶端)集成進來實現分布式鎖,也可以使用數據庫、Zookeeper等,具體可以參考:

分布式鎖的3種實現(數據庫、緩存、Zookeeper)

作者:mikechen

來源:https://mikechen.cc/16961.html

分享到:
標簽:Redis
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定