您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關如何理解分布式鎖中Redis鎖和ZK鎖,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
分布式系統中,常見的分布式鎖有兩種,一種是基于Redis實現的分布式鎖,一種是基于ZooKeeper鎖。本篇文章簡要介紹下其原理及方案。
先說上鎖的命令,上鎖的命令是:set {lockName} {randomVal} nx px 30000。
其中,nx 參數的意思是不存在鎖的時候設置,px參數表示毫秒數,該條命令表示當不存在lockName鍵的時候,為其設置值為randomVal,并設置過期時間為30000毫秒。當redis中存在該鍵是redis返回nil。其他線程(包括其他機器)來獲取鎖的時候,可以用輪詢來判斷是否上鎖成功,達到阻塞其他線程的目的。
解鎖,我們需要實現的需求是不能刪除掉其他線程設置的鎖。因為某些情況比如鎖超時,其他線程還是會獲取到鎖。所以必須先判斷鎖是不是自己設置的再進行刪除,由于redis沒有提供一個原子命令判斷當前值是什么再進行刪除,所以必須向redis傳入lua腳本以確保解鎖操作的原子性。解鎖的原理是傳入隨機值進行解鎖,腳本中會判斷當前Key存不存在,存在的話再判斷值是否與傳入的隨機值相等,相等則將其刪除。
這種上鎖方案有很明顯的的缺點,如:
一是這種方案并不是很可靠,被上鎖的redis宕機后容易丟數據,就算是配置了哨兵,也存在主備切換的時候可能丟數據。
二是不能實現公平鎖。
三是輪詢阻塞這種方式開銷有點大。
四是不可實現線程重入。
沒有續約機制
針對第一點,redis官方建議使用基于redisCluster的redlock(紅鎖)方案。這種方案核心要點就是需要在大多數redis節點上獲取鎖成功才算成功。但這就意味著開銷變大了,并且針對紅鎖這種方案,網絡上也有些大佬們提出質疑。
這種簡單版本的redis分布式鎖方案并不能解決這些問題,如果要解決可以使用redission框架,redission運用了隊列、redis發布訂閱機制,看門狗機制,較為復雜的加鎖、釋放鎖腳本解決了這些問題。redission支持可重入鎖、公平鎖、紅鎖等,并且將redis鎖按JDK的Lock接口進行了封裝,操作簡單易用。
以在ZooKeeper中成功創建臨時節點為標識,創建成功則獲取鎖成功,創建失敗則監聽該節點,直到節點刪除在嘗試創建臨時節點。 為什么使用臨時節點?避免服務宕機,導致死鎖問題。
刪除節點即解鎖成功。
這種方案的缺點是鎖是不公平的,并且節點刪除喚醒的其他監聽線程比較多,效率沒有接下來介紹的使用臨時順序節點的方案只喚醒下一個監聽節點的方式高。
每次嘗試獲取鎖都嘗試創建一個臨時順序節點,并且獲取當且父節點下的所有臨時順序節點,如果前面還有節點,則獲取鎖不成功,此時將主線程阻塞,監聽前面一個節點被刪除,如果被刪除再喚醒主線程。反之如果當前創建的臨時順序節點前面沒有節點則獲取鎖成功。
刪除當前臨時順序節點即解鎖成功。
這種方案實現的是公平鎖,以前的并發競爭ZK臨時節點創建,改為依次喚醒,降低了一定開銷。
個人覺得對于分布式系統來說,redisCluster紅鎖的設計不是很優雅,感覺基于zookeeper集群高可用的zk鎖更優雅一些。所以如果做技術選型的話,個人傾向zk鎖。但是如果技術架構中沒有搭建zookeeper,可能選擇的是springcloud那一套,選擇redisssion封裝的redis鎖也行。
看完上述內容,你們對如何理解分布式鎖中Redis鎖和ZK鎖有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。