1. 程式人生 > >分布式鎖實現方案

分布式鎖實現方案

樂觀鎖 .com 樂觀 zookeeper 阻塞 zook session 業務邏輯 客戶端連接

一、單機模式

在這種情況下,如果我們實現鎖可以使用synchronized或ReentrantLock,但是在分布式情況下,它們最多只能鎖住當前JVM的線程,對於其它server的線程無能為力。那麽怎麽處理呢?

二、分布式鎖

1、基於數據庫表做樂觀鎖

一般是通過為數據庫表添加一個 “version”字段來實現讀取出數據時,將此版本號一同讀出,之後更新時,對此版本號加1。在更新過程中,會對版本號進行比較,如果是一致的,沒有發生改變,則會成功執行本次操作;如果版本號不一致,則會更新失敗。

2、使用memcached的add()方法

該命令只有KEY不存在時,才進行添加,或者不會處理。Memcached 所有命令都是原子性的,並發下add 同一個KEY ,只會一個會成功。

我們需要在add()的使用指定當前添加的這個key的有效時間,如果不指定有效時間,正常情況下執行完自己的業務後,使用delete方法將這個key刪除掉,也就是釋放了占用的資源。但是,如果在占位成功後,memecached或者自己的業務服務器發生宕機了,那麽這個資源將無法得到釋放。所以通過對key設置超時時間,即便發生了宕機的情況,也不會將資源一直占用,可以避免死鎖的問題。

3、使用redis的setnx()、expire()方法

這個方案相對於memcached()的add()方案,redis占優勢的是,其支持的數據類型更多,而memcached只支持String一種數據類型。

具體使用步驟如下:

  1. setnx()該方法是原子的,如果key不存在,則設置當前key成功,返回1;如果當前key已經存在,則設置當前key失敗,返回0;
  2. 但是要註意的是setnx命令不能設置key的超時時間,只能通過expire()來對key設置;
  3. 執行完業務代碼後,通過delete命令立即刪除key。

4、zookeeper分布式鎖

首先我們來了解一下zookeeper的特性,看看它為什麽適合做分布式鎖,

  zookeeper是一個為分布式應用提供一致性服務的軟件,它內部是一個分層的文件系統目錄樹結構,規定統一個目錄下只能有一個唯一文件名。

數據模型:

  • 永久節點:節點創建後,不會因為會話失效而消失

  • 臨時節點:與永久節點相反,如果客戶端連接失效,則立即刪除節點

  • 順序節點:與上述兩個節點特性類似,如果指定創建這類節點時,zk會自動在節點名後加一個數字後綴,並且是有序的。

  監視器(watcher):

  • 當創建一個節點時,可以註冊一個該節點的監視器,當節點狀態發生改變時,watch被觸發時,ZooKeeper將會向客戶端發送且僅發送一條通知,因為watch只能被觸發一次。

根據zookeeper的這些特性,我們來看看如何利用這些特性來實現分布式鎖:

  1. 創建一個鎖目錄lock

  2. 希望獲得鎖的線程A就在lock目錄下,創建臨時順序節點

  3. 獲取鎖目錄下所有的子節點,然後獲取比自己小的兄弟節點,如果不存在,則說明當前線程順序號最小,獲得鎖

  4. 線程B獲取所有節點,判斷自己不是最小節點,設置監聽(watcher)比自己次小的節點(只關註比自己次小的節點是為了防止發生“羊群效應”)

  5. 線程A處理完,刪除自己的節點,線程B監聽到變更事件,判斷自己是最小的節點,獲得鎖。

使用zookeeper的優點

  • 鎖無法釋放?使用Zookeeper可以有效的解決鎖無法釋放的問題,因為在創建鎖的時候,客戶端會在ZK中創建一個臨時節點,一旦客戶端獲取到鎖之後突然掛掉(Session連接斷開),那麽這個臨時節點就會自動刪除掉。其他客戶端就可以再次獲得鎖。

  • 非阻塞鎖?使用Zookeeper可以實現阻塞的鎖,客戶端可以通過在ZK中創建順序節點,並且在節點上綁定監聽器,一旦節點有變化,Zookeeper會通知客戶端,客戶端可以檢查自己創建的節點是不是當前所有節點中序號最小的,如果是,那麽自己就獲取到鎖,便可以執行業務邏輯了。

  • 不可重入?使用Zookeeper也可以有效的解決不可重入的問題,客戶端在創建節點的時候,把當前客戶端的主機信息和線程信息直接寫入到節點中,下次想要獲取鎖的時候和當前最小的節點中的數據比對一下就可以了。如果和自己的信息一樣,那麽自己直接獲取到鎖,如果不一樣就再創建一個臨時的順序節點,參與排隊。

  • 單點問題?使用Zookeeper可以有效的解決單點問題,ZK是集群部署的,只要集群中有半數以上的機器存活,就可以對外提供服務。

參考文章:https://www.cnblogs.com/austinspark-jessylu/p/8043726.html

分布式鎖實現方案