基於Mysql實現分布式鎖


一.分布式鎖要解決的問題

可以保證在分布式部署的應用集群中,同一個方法在同一時間只能被一台機器上的一個線程執行。

這把鎖要是一把可重入鎖(避免死鎖)

這把鎖最好是一把阻塞鎖(根據業務需求考慮要不要這條)

這把鎖最好是一把公平鎖(根據業務需求考慮要不要這條)

有高可用的獲取鎖和釋放鎖功能

獲取鎖和釋放鎖的性能要好

二.基於數據庫實現原理

1.新建鎖表記錄

CREATE TABLE `methodLock` ( 
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',  
`method_name` varchar(64) NOT NULL DEFAULT '' COMMENT '鎖定的方法名',
`desc` varchar(1024) NOT NULL DEFAULT '備注信息',  
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '保存數據時間,自動生成',  
PRIMARY KEY (`id`),  
UNIQUE KEY `uidx_method_name` (`method_name `) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='鎖定中的方法';

2.第一種實現

當想要鎖住某個方法時執行insert方法,插入一條數據,method_name有唯一約束,可以保證多次提交只有一次成功,而成功的這次就可以認為其獲得了鎖,而執行完成后執行delete語句釋放鎖

缺點:

這把鎖強依賴數據庫的可用性,數據庫是一個單點,一旦數據庫掛掉,會導致業務系統不可用。

這把鎖沒有失效時間,一旦解鎖操作失敗,就會導致鎖記錄一直在數據庫中,其他線程無法再獲得到鎖。

這把鎖只能是非阻塞的,因為數據的insert操作,一旦插入失敗就會直接報錯。沒有獲得鎖的線程並不會進入排隊隊列,要想再次獲得鎖就要再次觸發獲得鎖操作。

這把鎖是非重入的,同一個線程在沒有釋放鎖之前無法再次獲得該鎖。因為數據中數據已經存在了。

這把鎖是非公平鎖,所有等待鎖的線程憑運氣去爭奪鎖。

3.第二種實現

還是使用上方的表結構,可以通過數據庫的排他鎖來實現分布式鎖

在查詢語句后面增加for update,數據庫會在查詢過程中給數據庫表增加排他鎖。當某條記錄被加上排他鎖之后,其他線程無法再在該行記錄上增加排他鎖。

我們可以認為獲得排它鎖的線程即可獲得分布式鎖,當獲取到鎖之后,可以執行方法的業務邏輯,執行完方法之后,再通過connection.commit();操作來釋放鎖

代碼:

 

  1. public boolean lock(){

  2. connection.setAutoCommit(false)

  3. while(true){

  4. try{

  5. result = select * from methodLock where method_name=xxx for update;

  6. if(result==null){

  7. return true;

  8. }

  9. }catch(Exception e){

  10.  

  11. }

  12. sleep(1000);

  13. }

  14. return false;
    }

    1. public void unlock(){

    2. connection.commit();

    3. }

 

4.樂觀鎖實現

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

 

缺點:

 

(1). 這種操作方式,使原本一次的update操作,必須變為2次操作: select版本號一次;update一次。增加了數據庫操作的次數。

 

(2). 如果業務場景中的一次業務流程中,多個資源都需要用保證數據一致性,那么如果全部使用基於數據庫資源表的樂觀鎖,就要讓每個資源都有一張資源表,這個在實際使用場景中肯定是無法滿足的。而且這些都基於數據庫操作,在高並發的要求下,對數據庫連接的開銷一定是無法忍受的。

 

(3). 樂觀鎖機制往往基於系統中的數據存儲邏輯,因此可能會造成臟數據被更新到數據庫中。

總結

數據庫鎖現在使用較多的就上面說的3種方式,排他鎖(悲觀鎖),版本號(樂觀鎖),記錄鎖,各有優缺點

數據庫鎖的優點就是 直接借助DB簡單易懂

缺點也很明顯:

會有各種各樣的問題,在解決問題的過程中會使整個方案變得越來越復雜。

操作數據庫需要一定的開銷,性能問題需要考慮

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM