redis分布式鎖實現原理是什么

借助于redis中的命令setnx(key, value),key不存在就新增,存在就什么都不做。同時有多個客戶端發送setnx命令,只有一個客戶端可以成功,返回1(true);其他的客戶端返回0(false)。

redis分布式鎖實現原理是什么

本教程操作環境:windows7系統、Redis5.0.10版、DELL G3電腦。

分布式鎖的實現

隨著業務發展的需要,原單體單機部署的系統被演化成分布式集群系統后,由于分布式系統多線程、多進程并且分布在不同機器上,這將使原單機部署情況下的并發控制鎖策略失效,單純的Java API并不能提供分布式鎖的能力。為了解決這個問題就需要一種跨JVM的互斥機制來控制共享資源的訪問,這就是分布式鎖要解決的問題!

分布式鎖主流的實現方案:

  • 基于數據庫實現分布式鎖

  • 基于緩存(Redis等)

  • 基于Zookeeper

這里,我們就基于redis實現分布式鎖。

基本實現

借助于redis中的命令setnx(key, value),key不存在就新增,存在就什么都不做。同時有多個客戶端發送setnx命令,只有一個客戶端可以成功,返回1(true);其他的客戶端返回0(false)。

redis分布式鎖實現原理是什么

主要使用Redis Setnx 命令

在指定的 key 不存在時,為 key 設置指定的值

設置成功,返回 1 。 設置失敗,返回 0

redis>?EXISTS?job????????????????#?job?不存在  (integer)?0  ?  redis>?SETNX?job?"programmer"????#?job?設置成功  (integer)?1  ?  redis>?SETNX?job?"code-farmer"???#?嘗試覆蓋?job?,失敗  (integer)?0  ?  redis>?GET?job???????????????????#?沒有被覆蓋  "programmer"

java代碼

	public?void?testLock()?{  		//?執行redis的setnx命令  		String?uuid?=?UUID.randomUUID().toString();  		Boolean?lock?=?redisTemplate.opsForValue().setIfAbsent("lock",?uuid,?5,?TimeUnit.SECONDS);  ?  		//?判斷是否拿到鎖  		if?(lock)?{  			//?執行業務邏輯代碼  			//?...  ?  			//?釋放鎖資源?(保證獲取值和刪除操作的原子性)?LUA腳本保證刪除的原子性  			String?script?=?"if?redis.call('get',?KEYS[1])?==?ARGV[1]?then ?return?redis.call('del',?KEYS[1])?else?return?0?end";  			this.redisTemplate.execute(new?DefaultRedisScript(script),? Arrays.asList("lock"),?Arrays.asList(uuid));  //			if?(StrUtil.equals(uuid,redisTemplate.opsForValue().get("lock"))){  //				redisTemplate.delete("lock");  //			}  		}?else?{  			//?其他請求嘗試獲取鎖  			testLock();  		}  	}

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

互斥性。在任意時刻,只有一個客戶端能持有鎖。

不會發生死鎖。即使有一個客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保證后續其他客戶端能加鎖。

解鈴還須系鈴人。加鎖和解鎖必須是同一個客戶端,客戶端自己不能把別人加的鎖給解了。

相關教程推薦:Redis教程

以上就是

? 版權聲明
THE END
喜歡就支持一下吧
點贊11 分享