首頁 >資料庫 >Redis >redis分散式鎖實作原理是什麼

redis分散式鎖實作原理是什麼

醉折花枝作酒筹
醉折花枝作酒筹原創
2021-06-23 11:57:193456瀏覽

借助於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教學

以上是redis分散式鎖實作原理是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn