分布式鎖實現的幾種方式

2021-10-11 03:26:07 字數 2527 閱讀 6603

準備條件:建立表abc,並做唯一索引version;

//1、執行緒a加鎖:

insert into abc(version)values (versionid);

//2、執行緒a釋放鎖:

delete from abc where version =versionid;

如果資料庫中有該鎖記錄,執行緒b再儲存資料進行加鎖就會發生唯一索引異常,這時就成功實現了分布式鎖;

缺點:只適用於併發量不大的業務場景,這裡xxl-job的管理後台上使用了這種方式;

容易發生死鎖,但是可以起乙個定時任務去清理它;

樂觀鎖主要根據加版本號的方式實現,原來如下:a、b執行緒執行更新操作之前先查詢版本號,然後根據版本號進行更新,如果版本號被執行緒a更新了,

這時執行緒b再用該版本號執行更新就會更新失敗,從而成功實現加鎖;這裡需要注意此種鎖為不可重入鎖,只能重新發起業務請求;

//1、查詢出資料庫中的版本號

select id,version from abc;//獲取到versionid

//2、對該條記錄進行更新

update abc set business = business-1 , version = versionid+1 where version=versionid and id =id;

這時如果執行緒b再用原來的versionid進行更新,就失敗了;

缺點:需要維護版本字段,造成資料庫表結構的冗餘;

只適用於併發不高,寫操作少的情況;

//1、由於mysql是預設自動事務提交的,這裡需要先關閉事務自動提交

set autocommit = 0;(有沒人知道使用spring事務的時候,怎麼不關閉自動提交呢?)

//2、對於innodb的資料表來說,支援表級鎖和行級鎖,當查詢時不走索引的時候加的就是表級鎖;對於myisam(不支援事務)的資料表,只支援表級鎖;

select * from abc where a.version =versionid for update;//行級鎖

select * from abc where a.version >versionid for update;//表級鎖

select * from abc where a.business =businessid for update;//表級鎖

//3、讀鎖屬於共享鎖,a執行緒對該條記錄上共享鎖後,b執行緒也可以上共享鎖,但不能上排它鎖;

寫鎖屬於排它鎖,a執行緒對該條記錄上排它鎖後,b執行緒不能再上任何鎖;

//4、這裡多補充一點oracel中有for update nowait語法,使用該語法不會像for update當該行被鎖定時一直等待,而是直接報錯;

mysql中可以是通過配置 innodb_lock_wait_timeout的時間指定該查詢會話等待的時間,超時就直接報錯

優點:redis是單執行緒執行的,所以它天然的支援分布式鎖

缺點:超時時間的設定不當,會對服務效能有較大影響(我們的專案設定的8s)

實現**如下:

//1、加鎖基於set key value [ex seconds|px milliseconds] [nx|xx];

ex 表示超時時間精度是秒

px 表示超時時間精度是毫秒

nx 表示只有當該key 不存在時才儲存

xx 表示只有當該key存在時才覆蓋

public

class

redistool

return

false;}

}

2、解鎖使用lua指令碼,保證操作的原子性

public

class

redistool

return

false;}

}

1、多個client共同去zk上預定義好的/lock節點下建立乙個相同的臨時節點/abc;

2、哪個節點建立成功之後,就說明該會話拿到了鎖;

3、其他建立失敗的client,繼續保持對該節點的監聽;

4、當之前拿到鎖的client會話結束或者主動釋放了鎖,這時其他的client再次去/lock下建立/abc,以便獲取鎖

缺點:每一次只有乙個client註冊成功,其他的client都會失敗,然後觸發監聽時還要通知每乙個client,再次去競爭鎖,這裡如果請求量大的話,會引發羊群效應,這裡可以嘗試使用共享鎖

1、當多個請求到來時,同樣去zk上預定義好的/lock節點下建立節點,但是是臨時有序節點/abc0000001,這樣每個請求都可以建立成功

2、當建立成功後,並不是每個節點都能夠拿到鎖,只有當前有序節點之前沒有其他節點,即當前節點的序號是最小的時候,才說明了該節點拿到了鎖;

3、拿到鎖的請求,會話結束後,刪除掉對應的臨時節點即可;

4、其他沒有拿到的鎖的請求只需要保持對它前乙個節點的監聽,當它前面的節點不存在了,自己變成了最小的序號了,這就說明自己拿到了鎖

未完待續。。。。。。

分布式鎖的幾種實現方式

現在的微服務系統,由於系統都是由多個微服務組成的,相比較於傳統的應用系統,鎖的實現就變的複雜了很多,單體應用的鎖也不適用與分布式系統,下面就介紹幾種分布式鎖的實現方式,常見的分布式鎖的實現方式有資料庫分布式鎖,redis分布式鎖,zookeeper分布式鎖 一 資料庫分布式鎖 1 利用資料庫記錄的唯...

分布式鎖實現方式

1 資料庫的唯一索引實現 獲得鎖時向表中插入一條記錄,釋放鎖時刪除這條記錄。唯一索引可以保證該記錄只被插入一次,那麼就可以用這個記錄是否存在來判斷是否存於鎖定狀態。缺點 2 redis的setnx指令實現 使用 setnx set if not exist 指令插入乙個鍵值對,如果 key 已經存在...

分布式鎖的實現方式

在進行大型 技術架構設計以及業務實現的過程中,多少都會遇到需要使用分布式鎖的情況。那麼問題也就接踵而至。分布式鎖zk和memcached以及redis三者都能實現,同樣是分布式鎖,三者的區別何在?各自適用什麼場景?一 zookeeper 實現原理 基於zookeeper瞬時有序節點實現的分布式鎖,其...