分布式鎖的實現方式

2021-09-23 08:06:54 字數 3663 閱讀 7723

一、分布式鎖應該具備哪些條件

1、在分布式系統環境下,乙個方法在同一時間只能被乙個機器的乙個執行緒執行;

2、高可用高效能的獲取鎖和釋放鎖;

3、具備可重入特性;

4、具備鎖失效機制,防止死鎖;

5、具備非阻塞鎖特性,沒有獲取到鎖就直接返回獲取鎖失敗。

二、分布式鎖的實現方式

在很多場景中,我們為了保證資料的最終一致性,需要使用分布式事務,分布式鎖等。我們需要保證乙個方法在同一時間只能被同乙個執行緒執行。

基於資料庫實現分布式鎖;

基於快取(redis)實現分布式鎖;

基於zookeeper實現分布式鎖。

不同的業務要根據自己的情況進行選型,選擇合適的方案。

三 、基於資料庫的分布式鎖

在資料庫中建立乙個表,表中包含方法名等字段,並在方法名字段上加唯一索引,想要執行這個方法,就使用這個方法名向表中插入資料,成功插入則獲得鎖,執行完成後刪除對應資料釋放鎖。

(1)建立乙個表:

lock_name欄位作為唯一性索引

create table `cluster_lock` (

`lock_name` varchar(255) character set latin1 not null,

`ttl` int(11) not null,

`gmt_create` timestamp not null default current_timestamp on update current_timestamp,

unique key `lock_name_unique` (`lock_name`)

) engine=innodb default charset=utf8 collate=utf8_bin

獲取鎖,釋放鎖的方法

@service

public class lockserviceimpl implements lockservice else }}

public boolean getlock(string lockname, int ttl)

}clusterlockdo tryinsert = new clusterlockdo();

tryinsert.setlockname(lockname);

tryinsert.setttl(ttl);

boolean holdlock;

try catch (duplicatekeyexception duplicatekeyexception) catch (exception e)

return holdlock;

}public boolean getlock(string lockname)

public void releaselock(string lockname)

}

將方法打包成公共包

@feignclient(name = "service") //服務名

public inte***ce lockapi

在方法中使用鎖的方法,進行fegin呼叫服務

//獲取鎖

if (!lockapi.getlock(triggerlockkey, 30*1000).getdata().booleanvalue())

try finally

四、基於redis實現分布式鎖

1、redis實現分布式鎖的優點。

(1)redis有很高的效能; 

(2)redis命令對此支援較好,實現起來比較方便。

2、常用命令

(1) setnx key val:當且僅當key不存在時,set乙個key為val的字串,返回1;若key存在,則什麼都不做,返回0。

(2) expire key timeout:為key設定乙個超時時間,單位為second,超過這個時間鎖會自動釋放,避免死鎖。

(3) delete key:刪除key

3、實現思想

(1)獲取鎖的時候,使用setnx加鎖,並使用expire命令為鎖新增乙個超時時間,超過該時間則自動釋放鎖,鎖的value值為乙個隨機生成的uuid,通過此在釋放鎖的時候進行判斷。

(2)獲取鎖的時候還設定乙個獲取的超時時間,若超過這個時間則放棄獲取鎖。

(3)釋放鎖的時候,通過uuid判斷是不是該鎖,若是該鎖,則執行delete進行鎖釋放。

4、簡單**實現

@component

public class jedislockutil

private static boolean isjedis()

if (bean.getconnection().getnativeconnection() instanceof jedis) else if (bean.getconnection().getnativeconnection() instanceof jediscluster)

}return jedisflag;

}public static redisconnection getredisconnection() else

}public static boolean lock(string key, string requiredid, int expiretime)

string result = "";

if (isjedis()) else

if (!"ok".equals(result))

var5 = true;

return var5;

} catch (exception var9) finally

}return var5;

}public static boolean lock(string key, string requiredid)

public static boolean lock(string key, int expiretime)

public static boolean lock(string key)

public static boolean unlock(string lockkey, string requestid)

if (isjedis()) else

if (result == null)

long rt = 0l;

rt = (long)result;

boolean var7;

if (rt > 0l)

var7 = false;

return var7;

} catch (exception var11) finally

}return var5;

}public static boolean unlock(string key)

}

在方法中的使用

string key = caseservice.class.getcanonicalname() + "-createcase-" + casegroup.getbusinessid() + casegroup.gettitle();

string rid = uuidutil.getuuid();

if (lockutil.lock(key, rid)) catch (exception e) finally

分布式鎖實現方式

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

分布式鎖的實現方式

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

分布式鎖的實現方式

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