溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

mysql中怎么實現(xiàn)分布式鎖

發(fā)布時間:2022-01-20 16:40:00 來源:億速云 閱讀:390 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“mysql中怎么實現(xiàn)分布式鎖”,在日常操作中,相信很多人在mysql中怎么實現(xiàn)分布式鎖問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”mysql中怎么實現(xiàn)分布式鎖”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

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

可以保證在分布式部署的應(yīng)用集群中,同一個方法在同一時間只能被一臺機(jī)器上的一個線程執(zhí)行。

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

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

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

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

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

二.基于數(shù)據(jù)庫實現(xiàn)原理

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 '保存數(shù)據(jù)時間,自動生成',   PRIMARY KEY (`id`),   UNIQUE KEY `uidx_method_name` (`method_name `) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='鎖定中的方法';

2.第一種實現(xiàn)

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

缺點:

這把鎖強(qiáng)依賴數(shù)據(jù)庫的可用性,數(shù)據(jù)庫是一個單點,一旦數(shù)據(jù)庫掛掉,會導(dǎo)致業(yè)務(wù)系統(tǒng)不可用。

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

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

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

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

3.第二種實現(xiàn)

還是使用上方的表結(jié)構(gòu),可以通過數(shù)據(jù)庫的排他鎖來實現(xiàn)分布式鎖

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

我們可以認(rèn)為獲得排它鎖的線程即可獲得分布式鎖,當(dāng)獲取到鎖之后,可以執(zhí)行方法的業(yè)務(wù)邏輯,執(zhí)行完方法之后,再通過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. sleep(1000);

  12. }

  13. return false; }

    1. public void unlock(){
    2. connection.commit();
    3. }

4.樂觀鎖實現(xiàn)

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

缺點:

(1). 這種操作方式,使原本一次的update操作,必須變?yōu)?次操作: select版本號一次;update一次。增加了數(shù)據(jù)庫操作的次數(shù)。

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

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

到此,關(guān)于“mysql中怎么實現(xiàn)分布式鎖”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI