1. 程式人生 > >分布式鎖(1) ----- 介紹和基於數據庫的分布式鎖

分布式鎖(1) ----- 介紹和基於數據庫的分布式鎖

版本號 進程 sta commit 結構 urn 集群 stat true

線程鎖與分布式鎖

1.java的synchronize和Lock都是屬於線程鎖,只能保證同一個進程內的多線程對共享變量修改訪問同步。它們的原理都是設置一個可以讓所有線程訪問到標記,如synchronize是設置對象頭的Mark Word,而Lock類是基於AQS的volatile修飾的state。

2.分布式鎖是屬於進程範疇的,而且進程可以在不同的機器上。它要保證的是多個進程對共享變量修改訪問同步(例如集群環境下同時修改緩存和數據庫)。分布式鎖也同樣需要一個可以讓所有進程訪問到的標記(如數據庫的字段,redis的數據,zookeeper的節點等)來控制同步。

實現方法

1.基於數據庫的分布式鎖

2.基於redis的分布式鎖

3.基於zookeeper的分布式鎖

基於數據庫的分布式鎖

基於表主鍵唯一

利用主鍵具有唯一性的性質,加鎖時向數據庫插入以鎖名為主鍵的數據,解鎖時刪除該數據。
優化:
1.沒有過期時間,如果獲得鎖的服務解鎖失敗,將導致其他服務無法獲得鎖。網上也有解決方法:增加過期時間字段,定期清除過期鎖數據。
2.重入性,增加獲得鎖服務的標記字段。

基於版本號字段

為表結構增加版本號字段,每次獲取數據將版本號獲取到,下次修改數據時判斷當前版本是否該版本號。思路是與mysql的mvcc機制差不多的。

基於排他鎖

public boolean lock(){
    connection.setAutoCommit(false)
    while(true){
        try{
            result = select * from lock where lockName=xxx for update;
            if(result==null){
                return true;
            }
        }catch(Exception e){
 
        }
        sleep(1000);
    }
    return false;
}


public void unlock(){
    connection.commit();
}

1.該方法是基於mysql的innodb的行級鎖,所以lockName字段必須有索引存在,但因此也有一個問題,是否使用索引是有mysql來判斷的,如果mysql認為全表查詢更快,會使用表鎖,那將會影響lock表的所有分布式鎖。

2.for update會在執行失敗是一直阻塞到成功。

優缺點

優點:容易實現理解

缺點:占用數據庫連接,性能較低。

參考資料

https://www.cnblogs.com/seesun2012/p/9214653.html

分布式鎖(1) ----- 介紹和基於數據庫的分布式鎖