Redis單點方式:html
首先,Redis客戶端爲了獲取鎖,向Redis節點發送以下命令:node
SET resource_name my_random_value NX PX 30000
上面的命令若是執行成功,則客戶端成功獲取到了鎖,接下來就能夠訪問共享資源了;而若是上面的命令執行失敗,則說明獲取鎖失敗。redis
注意,在上面的SET
命令中:算法
my_random_value
是由客戶端生成的一個隨機字符串,它要保證在足夠長的一段時間內在全部客戶端的全部獲取鎖的請求中都是惟一的。NX
表示只有當resource_name
對應的key值不存在的時候才能SET
成功。這保證了只有第一個請求的客戶端才能得到鎖,而其它客戶端在鎖被釋放以前都沒法得到鎖。PX 30000
表示這個鎖有一個30秒的自動過時時間。固然,這裏30秒只是一個例子,客戶端能夠選擇合適的過時時間。最後,當客戶端完成了對共享資源的操做以後,執行下面的Redis Lua腳原本釋放鎖:數據庫
if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end
這段Lua腳本在執行的時候要把前面的my_random_value
做爲ARGV[1]
的值傳進去,把resource_name
做爲KEYS[1]
的值傳進去。服務器
總結:dom
1.必須設置過時時間,過時時間須要謹慎考慮,過短鎖沒等主動釋放就過時,太長一旦擁有鎖的對象出現問題,別人會很長時間沒法使用。異步
2.setnx 和 過時時間必須是原子的分佈式
3.value必須是隨機的,保證解鈴還須繫鈴人,別人解不了post
4.釋放必須用Lua原子方式進行。由於Get和Del是分佈進行的,沒髮指定刪除隨機value的key,因此必須原子性,防止刪除的時候不是本身的鎖,而是過時後別人加上去的鎖。
另外:單機的問題沒法達到高可用,當redis宕了後,鎖失效,經過slave方式處理也可能會有1s內的數據同步問題,若是正好遇上master上加上鎖,還沒同步到slave上,master宕,slave變成master時鎖不對。
多redis集羣方式:(客戶端須要作的事情太多,不太好用仍是用zk吧)
考慮:若是Client1 獲取lock1後,執行了Full GC,到了過時時間,lock1過時。Client2獲取lock2,執行數據操做。Client1恢復運行,執行數據操做!這樣兩個Client同時拿到了鎖。
可讓Lock Server在分配鎖的時候返回一個遞增數字,在執行數據操做的時候,須要提交這個數字,記錄最後一次執行的數字,而且只接受比這個數字大的請求。保證請求數據操做的Client是按拿到鎖的順序執行的。但redis暫時不能返回這個數字。
使用分佈式鎖的方式有兩種狀況:
結論:
http://zhangtielei.com/posts/blog-redlock-reasoning.html
一個基於ZooKeeper構建分佈式鎖的描述(固然這不是惟一的方式):
/lock
。那麼第一個客戶端就建立成功了,至關於拿到了鎖;而其它的客戶端會建立失敗(znode已存在),獲取鎖失敗。看起來這個鎖至關完美,沒有Redlock過時時間的問題,並且能在須要的時候讓鎖自動釋放。但仔細考察的話,並不盡然。
ZooKeeper是怎麼檢測出某個客戶端已經崩潰了呢?實際上,每一個客戶端都與ZooKeeper的某臺服務器維護着一個Session,這個Session依賴按期的心跳(heartbeat)來維持。若是ZooKeeper長時間收不到客戶端的心跳(這個時間稱爲Sesion的過時時間),那麼它就認爲Session過時了,經過這個Session所建立的全部的ephemeral類型的znode節點都會被自動刪除。
設想以下的執行序列:
/lock
,得到了鎖。/lock
被自動刪除。/lock
,從而得到了鎖。最後,客戶端1和客戶端2都認爲本身持有了鎖,衝突了。這與以前Martin在文章中描述的因爲GC pause致使的分佈式鎖失效的狀況相似。
ZooKeeper的watch機制。這個機制能夠這樣來使用,好比當客戶端試圖建立/lock
的時候,發現它已經存在了,這時候建立失敗,但客戶端不必定就此對外宣告獲取鎖失敗。客戶端能夠進入一種等待狀態,等待當/lock
節點被刪除的時候,ZooKeeper經過watch機制通知它,這樣它就能夠繼續完成建立操做(獲取鎖)。這可讓分佈式鎖在客戶端用起來就像一個本地的鎖同樣:加鎖失敗就阻塞住,直到獲取到鎖爲止。這樣的特性Redlock就沒法實現。
小結一下,基於ZooKeeper的鎖和基於Redis的鎖相比在實現特性上有兩個不一樣:
http://zhangtielei.com/posts/blog-redlock-reasoning-part2.html