基於Mysql實現分布式鎖

2022-05-08 13:00:15 字數 2002 閱讀 1136

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

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

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

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

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

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

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='鎖定中的方法';

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

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

這把鎖沒有失效時間,一旦解鎖操作失敗,就會導致鎖記錄一直在資料庫中,其他執行緒無法再獲得到鎖。

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

這把鎖是非重入的,同乙個執行緒在沒有釋放鎖之前無法再次獲得該鎖。因為資料中資料已經存在了。

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

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

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

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

**:publicbooleanlock()

}catch(exceptione)

sleep(1000);

}returnfalse;

}publicvoidunlock()

一般是通過為資料庫表新增乙個 「version」欄位來實現讀取出資料時,將此版本號一同讀出,之後更新時,對此版本號加1,在更新過程中,會對版本號進行比較,如果是一致的,沒有發生改變,則會成功執行本次操作;如果版本號不一致,則會更新失敗,實際就是個diff過程

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

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

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

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

資料庫鎖的優點就是 直接借助db簡單易懂

缺點也很明顯:

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

運算元據庫需要一定的開銷,效能問題需要考慮

基於Redis實現分布式鎖

分布式鎖的基本功能 1.同一時刻只能存在乙個鎖 2.需要解決意外死鎖問題,也就是鎖能超時自動釋放 3.支援主動釋放鎖 分布式鎖解決什麼問題 多程序併發執行任務時,需要保證任務的有序性或者唯一性 準備 redis版本 2.6 redis是主從 sentinel模式 為了高可用 原理 redis2.6之...

基於 redis setNx 分布式鎖實現

public class redislock public redislock string lockkey,int timeoutmsecs public redislock string lockkey,int timeoutmsecs,int expiremsecs public string...

基於Redis實現分布式鎖

之前專案中使用redis鎖實現秒殺等一些併發業務,在這裡整理一下基於redis實現分布式鎖的簡單入門例項,記錄一下,便於以後檢視 學習。springboot整合redisson分布式鎖 1 簡介 在分布式系統中存在併發場景,為了解決這一問題,基於redis鎖一定程度可以解決這一問題,但是也有缺點,如...