先來講說什麼是分佈式鎖,簡單來講,分佈式鎖就是在分佈式併發場景中,可以實現多節點的代碼同步的一種機制。從實現角度來看,主要有兩種方式:基於redis的方式和基於zookeeper的方式,下面分別簡單介紹下這兩種方式:html
請尊重做者勞動成果,轉載請標明原文連接:node
http://www.javashuo.com/article/p-rjgwjyjv-db.htmlweb
1、基於redis的分佈式鎖實現redis
1.獲取鎖 數據庫
redis是一種key-value形式的NOSQL數據庫,經常使用於做服務器的緩存。從redis v2.6.12開始,set命令開始變成以下格式:緩存
除key和value外,EX是超時時間,NX表示只有在key不存在的時候纔會設置key的值,而XX表示在key存在的時間纔會設置key的值。NX機制就是基於redis分佈式鎖的核心。可以解決如下問題:服務器
1)節點1獲取key,而且設置超時時間後,還沒來得及釋放就掛掉了——這裏EX超時時間會發揮做用,超時後自動釋放鎖。併發
2)剛獲取到鎖,還沒來得及設置超時時間就掛了——這裏設置key和設置超時時間是原子操做,若是出現這種狀況,會返回0,即獲取不到鎖。分佈式
2.釋放鎖lua
爲了解決非原子操做帶來的問題,常採用lua腳本實現。lua腳本的操做會被認爲是原子性的,相似於事務。僞代碼以下:
String luaScript =
"if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
redisClient.eval(luaScript , Collections.singletonList(key), Collections.singletonList(threadId));
2、基於zookeeper的分佈式鎖實現
zookeeper是一種分佈式協調服務,其中每一個節點稱爲znode,並有本身獨立的路徑。 znode有四種類型:
下面看看是怎樣基於上面的四類節點實現分佈式鎖的。
1.獲取鎖
2.釋放鎖
釋放鎖就比較簡單了,由於前面建立的臨時順序節點,因此在出現下面兩種狀況時,都會自動釋放鎖:
1)任務完成後,Client會釋放鎖。
2)任務沒完成,Client就崩潰了,也會自動釋放鎖。