分佈式鎖實現---redis和zookeeper

可基於以下三種原則來進行鎖設計

	獨享,無死鎖,容錯(大部分Redis節點都活着,客戶端就可以獲取和釋放鎖.)

1. Redis分佈式鎖

	簡單版: 1. setNx key value 原子操作,只有當key不存在時才能設置成功(獨享)
			2. expire key aliveTime 如果獲得鎖的客戶端宕機,則鎖會在aliveTime後釋放(無死鎖)

簡單版存在的問題

	1. setNx和expire合在一起時,非原子性操作
	2. 過期時間到了,但結點1任務未執行完畢還沒主動釋放鎖(時間到了,已被被動刪除),結點2會拿到鎖。
	   矛盾所在處:兩個結點都擁有鎖,且都以爲只有自己擁有鎖。
	   2.1)結點1的JVM進程執行完畢,要釋放鎖,執行del命令,但此時刪除的可能是結點2的鎖
	   2.2)此時確實有兩個結點拿到鎖了(不符合獨佔原則)
	3. 如果在redis主從複製異步模式下,當結點1在master上剛設置了鎖,但還沒同步到slaver就宕機了。此時結點2在新master上設置了鎖,這就導致有多個結點擁有了鎖(不符合獨佔原則)

進化版Redis分佈式鎖

	1.SET resource_name my_random_value NX PX 30000
	2. 使用Lua腳本,驗證和刪除過程就是原子操作
	   if redis.call("get",KEYS[1]) == ARGV[1] then
		 return redis.call("del",KEYS[1])
	   else
	     return 0
	   end
	3.獲得鎖的線程開啓一個守護線程,給快要過期的鎖續航,當結點1斷電或宕機,由於守護線程和獲得鎖的線程在一個進程裏,所以守護線程也會停止,由於沒有守護線程給它續航,到期後會自動釋放鎖

2. Zookeeper分佈式鎖

Zookeeper中的四種類型的結點

	1. 持久化目錄結點:創建結點的客戶端與zk斷開連接後,結點仍存在
	2. 持久化順序編號目錄結點:創建節點時zk根據創建的時間順序給該節點名稱進行編號
	3. 臨時目錄結點:創建結點的客戶端與zk斷開連接後,結點就被刪除了
	4. 臨時順序編號目錄結點

結點也就是ZNode裏包含了什麼?

	1.data: Znode存儲的數據信息
	2.acl:Znode的訪問權限
	3.stat:Znode的各種元數據,事務id,版本號,時間戳等
	4.child:當前結點的子節點引用

zookeeper分佈式鎖實現原理

	每一個要獲得鎖的客戶端都要經歷如下過程
	1. 創建臨時順序結點
	2. 獲得當前根節點下的子節點,由小到大進行排序
	3. 判斷自己是否是第一個結點,即最小的
	   3.1)是,則成功獲得鎖
	   3.2)不是,則watch前一個結點(排好序的),如果watch到前一個結點發生刪除事件,則重複第三步驟
	4. 釋放鎖
	   4.1)正常執行結束,顯示釋放鎖,即刪除結點
	   4.2)拿到鎖的客戶端在執行任務中宕機了,那也沒關係,因爲隨着該客戶端與zk斷開連接,所創建的結點會被自動刪除
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章