国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【征服redis15】分布式鎖的功能與整體設(shè)計方案

這篇具有很好參考價值的文章主要介紹了【征服redis15】分布式鎖的功能與整體設(shè)計方案。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

目錄

?1. 分布式鎖的概念

2.基于數(shù)據(jù)庫做分布式鎖

2.1 基于表主鍵唯一做分布式鎖

2.2 基于表字段版本號做分布式鎖

2.3 基于數(shù)據(jù)庫排他鎖做分布式鎖

3.使用Redis做分布式鎖

3.1 redis實現(xiàn)分布式鎖的基本原理

3.2 問題一:增加超時機制,防止長期持有的情況

3.3 問題2:重入的問題

3.4 問題三:優(yōu)化輪詢加鎖的問題

3.4 總結(jié)

?1. 分布式鎖的概念

從現(xiàn)在開始,我們來研究分布式鎖相關(guān)的問題。在單機環(huán)境下,我們可以使用JDK提供的大量工具來完成線程安全與高并發(fā)相關(guān)的任務(wù),這其中最重要的一個就是鎖。

在單進程的系統(tǒng)中,當存在多個線程可以同時改變某個變量(可變共享變量)時,就需要對變量或代碼塊做同步,使其在修改這種變量時能夠線性執(zhí)行消除并發(fā)修改變量。而同步的本質(zhì)是通過鎖來實現(xiàn)的。為了實現(xiàn)多個線程在一個時刻同一個代碼塊只能有一個線程可執(zhí)行,那么需要在某個地方做個標記,這個標記必須每個線程都能看到,當標記不存在時可以設(shè)置該標記,其余后續(xù)線程發(fā)現(xiàn)已經(jīng)有標記了則等待擁有標記的線程結(jié)束同步代碼塊取消標記后再去嘗試設(shè)置標記。這個標記可以理解為鎖。

不同地方實現(xiàn)鎖的方式也不一樣,只要能滿足所有線程都能看得到標記即可。如 Java 中 synchronize 是在對象頭設(shè)置標記,JUC包里的Lock 接口的實現(xiàn)類基本上都只是某一個 volitile 修飾的 int 型變量其保證每個線程都能擁有對該 int 的可見性和原子修改,linux 內(nèi)核中也是利用互斥量或信號量等內(nèi)存數(shù)據(jù)做標記。

除了利用內(nèi)存數(shù)據(jù)做鎖其實任何互斥的都能做鎖(只考慮互斥情況),如流水表中流水號與時間結(jié)合做冪等校驗可以看作是一個不會釋放的鎖,或者使用某個文件是否存在作為鎖等。只需要滿足在對標記進行修改能保證原子性和內(nèi)存可見性即可。

如果我們思考一下,如果是在分布式場景下,又該如何實現(xiàn)共享變量的安全訪問呢?很多時候我們需要保證一個方法在同一時間內(nèi)只能被同一個線程執(zhí)行。在單機環(huán)境中,通過 Java 提供的并發(fā) API 我們可以解決,但是在分布式環(huán)境下,就沒有那么簡單啦。其中最典型的問題是:

  1. 分布式與單機情況下最大的不同在于其不是多線程而是多進程。
  2. 多線程由于可以共享堆內(nèi)存,因此可以簡單的采取內(nèi)存作為標記存儲位置。而進程之間甚至可能都不在同一臺物理機上,因此需要將標記存儲在一個所有進程都能看到的地方。

為此,我們就需要來設(shè)計分布式環(huán)境下可以保證資源安全訪問的鎖。具體來說,應(yīng)該滿足如下幾個要求:

  1. 在分布式模型下,數(shù)據(jù)只有一份(或有限制),此時需要利用鎖的技術(shù)控制某一時刻修改數(shù)據(jù)的進程數(shù)。
  2. 與單機模式下的鎖不僅需要保證進程可見,還需要考慮進程與鎖之間的網(wǎng)絡(luò)問題。分布式情況下之所以問題變得復(fù)雜,主要就是需要考慮到網(wǎng)絡(luò)的延時和不可靠。
  3. 分布式鎖還是可以將標記存在內(nèi)存,只是該內(nèi)存不是某個進程分配的內(nèi)存而是公共內(nèi)存如 Redis、Memcache。至于利用數(shù)據(jù)庫、文件等做鎖與單機的實現(xiàn)是一樣的,只要保證標記能互斥就行。

該如何實現(xiàn)分布式鎖呢?在Java領(lǐng)域,主要有三個組件可以幫助我們實現(xiàn):Mysql數(shù)據(jù)庫、redis和Zookeeper。我們分別來看如何使用這三個組件實現(xiàn)分布式鎖。

2.基于數(shù)據(jù)庫做分布式鎖

我們知道,即使在復(fù)雜的微服務(wù)環(huán)境下,我們最終要訪問的數(shù)據(jù)只會在一個地方,例如某個學(xué)生某個時間學(xué)習(xí)某課的記錄一定是在一個表里的(不考慮主備和異地?;畹囊蛩?,而不會將這個數(shù)據(jù)存放在好幾個地方,因此,不管有幾個請求,只要最后在訪問這條記錄的時候,我們實現(xiàn)安全訪問 ,其他的請求等待或者拒絕掉,就可以做到分布式鎖的效果。

這就是數(shù)據(jù)庫可以做分布式鎖的核心思想,具體來說,根據(jù)數(shù)據(jù)庫表的情況,我們又有多種方案。

2.1 基于表主鍵唯一做分布式鎖

利用主鍵唯一的特性,如果有多個請求同時提交到數(shù)據(jù)庫的話,數(shù)據(jù)庫會保證只有一個操作可以成功,那么我們就可以認為操作成功的那個線程獲得了該方法的鎖,當方法執(zhí)行完畢之后,想要釋放鎖的話,刪除這條數(shù)據(jù)庫記錄即可。

上面這種簡單的實現(xiàn)有以下幾個問題:

  • 這把鎖強依賴數(shù)據(jù)庫的可用性,數(shù)據(jù)庫是一個單點,一旦數(shù)據(jù)庫掛掉,會導(dǎo)致業(yè)務(wù)系統(tǒng)不可用。
  • 這把鎖沒有失效時間,一旦解鎖操作失敗,就會導(dǎo)致鎖記錄一直在數(shù)據(jù)庫中,其他線程無法再獲得到鎖。
  • 這把鎖只能是非阻塞的,因為數(shù)據(jù)的 insert 操作,一旦插入失敗就會直接報錯。沒有獲得鎖的線程并不會進入排隊隊列,要想再次獲得鎖就要再次觸發(fā)獲得鎖操作。
  • 這把鎖是非重入的,同一個線程在沒有釋放鎖之前無法再次獲得該鎖。因為數(shù)據(jù)中數(shù)據(jù)已經(jīng)存在了。
  • 這把鎖是非公平鎖,所有等待鎖的線程憑運氣去爭奪鎖。
  • 在 MySQL 數(shù)據(jù)庫中采用主鍵沖突防重,在大并發(fā)情況下有可能會造成鎖表現(xiàn)象。

當然,我們也可以有其他方式解決上面的問題。

  • 數(shù)據(jù)庫是單點?搞兩個數(shù)據(jù)庫,數(shù)據(jù)之前雙向同步,一旦掛掉快速切換到備庫上。
  • 沒有失效時間?只要做一個定時任務(wù),每隔一定時間把數(shù)據(jù)庫中的超時數(shù)據(jù)清理一遍。
  • 非阻塞的?搞一個 while 循環(huán),直到 insert 成功再返回成功。
  • 非重入的?在數(shù)據(jù)庫表中加個字段,記錄當前獲得鎖的機器的主機信息和線程信息,那么下次再獲取鎖的時候先查詢數(shù)據(jù)庫,如果當前機器的主機信息和線程信息在數(shù)據(jù)庫可以查到的話,直接把鎖分配給他就可以了。
  • 非公平的?再建一張中間表,將等待鎖的線程全記錄下來,并根據(jù)創(chuàng)建時間排序,只有最先創(chuàng)建的允許獲取鎖。
  • 比較好的辦法是在程序中生產(chǎn)主鍵進行防重。

不過整體來看,在復(fù)雜場景下,這個分布式鎖會非常脆弱,很容易出問題。

2.2 基于表字段版本號做分布式鎖

這個策略源于 mysql 的 mvcc 機制,使用這個策略其實本身沒有什么問題,唯一的問題就是對數(shù)據(jù)表侵入較大,我們要為每個表設(shè)計一個版本號字段,然后寫一條判斷 sql 每次進行判斷,增加了數(shù)據(jù)庫操作的次數(shù),但是在高并發(fā)的要求下,這會嚴重影響性能,對數(shù)據(jù)庫連接的開銷也是無法忍受的。

2.3 基于數(shù)據(jù)庫排他鎖做分布式鎖

在查詢語句后面增加for update,數(shù)據(jù)庫會在查詢過程中給數(shù)據(jù)庫表增加排他鎖 (注意: InnoDB 引擎在加鎖的時候,只有通過索引進行檢索的時候才會使用行級鎖,否則會使用表級鎖。這里我們希望使用行級鎖,就要給要執(zhí)行的方法字段名添加索引,值得注意的是,這個索引一定要創(chuàng)建成唯一索引,否則會出現(xiàn)多個重載方法之間無法同時被訪問的問題。重載方法的話建議把參數(shù)類型也加上。當某條記錄被加上排他鎖之后,其他線程無法再在該行記錄上增加排他鎖。

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

這種方法可以有效的解決上面提到的無法釋放鎖和阻塞鎖的問題。

  • 這種鎖是阻塞鎖,for update語句會在執(zhí)行成功后立即返回,在執(zhí)行失敗時一直處于阻塞狀態(tài),直到成功。
  • 這種鎖定之后服務(wù)宕機,是否會出現(xiàn)無法釋放的問題呢?使用這種方式,服務(wù)宕機之后數(shù)據(jù)庫會自己把鎖釋放掉。

所以這種方式比較簡單在實際工程里是很多應(yīng)用的。例如在轉(zhuǎn)賬的時候,我們需要先從A扣減10,然后再給B加10,此時就可以使用for update,保證這個操作要么一定完成,要么都不執(zhí)行。

這里可能有一個問題,就是我們要使用排他鎖來進行分布式鎖的 lock,那么一個排他鎖長時間不提交,就會占用數(shù)據(jù)庫連接。一旦類似的連接變得多了,就可能把數(shù)據(jù)庫連接池撐爆。

而且,這種方式還是無法直接解決數(shù)據(jù)庫單點和可重入問題,適合處理比較簡單的分布式鎖問題。

優(yōu)點:簡單,易于理解

缺點:會有各種各樣的問題(操作數(shù)據(jù)庫需要一定的開銷,使用數(shù)據(jù)庫的行級鎖并不一定靠譜,性能不靠譜)

3.使用Redis做分布式鎖

這個是我們后面要重點學(xué)習(xí)方式,做分布式鎖是redis的一大強項。

這篇文章寫的不錯,我們直接參考啦!

3.1 redis實現(xiàn)分布式鎖的基本原理

我們主要使用redis的setnx命令來實現(xiàn)。setnxSET if not exists(如果不存在,則 SET)的簡寫。

先看一個例子:

127.0.0.1:6379> setnx lock value1 #在鍵lock不存在的情況下,將鍵key的值設(shè)置為value1 (integer) 1

127.0.0.1:6379> setnx lock value2 #試圖覆蓋lock的值,返回0表示失敗

(integer) 0 127.0.0.1:6379> get lock #獲取lock的值,驗證沒有被覆蓋 "value1"

127.0.0.1:6379> del lock #刪除lock的值,刪除成功

(integer) 1

127.0.0.1:6379> setnx lock value2 #再使用setnx命令設(shè)置,返回0表示成功

(integer) 1 127.0.0.1:6379> get lock #獲取lock的值,驗證設(shè)置成功

"value2"

上面這幾個命令就是最基本的用來完成分布鎖的命令。

加鎖:使用setnx key value命令,如果key不存在,設(shè)置value(加鎖成功)。如果已經(jīng)存在lock(也就是有客戶端持有鎖了),則設(shè)置失敗(加鎖失敗)。

解鎖:使用del命令,通過刪除鍵值釋放鎖。釋放鎖之后,其他客戶端可以通過setnx命令進行加鎖。

key的值可以根據(jù)業(yè)務(wù)設(shè)置,比如是用戶中心使用的,可以命令為USER_REDIS_LOCK,value可以使用uuid保證唯一,用于標識加鎖的客戶端。保證加鎖和解鎖都是同一個客戶端。

那么接下來就可以寫一段很簡單的加鎖代碼:

private static Jedis jedis = new Jedis("127.0.0.1");

private static final Long SUCCESS = 1L;

/**
  * 加鎖
  */
public boolean tryLock(String key, String requestId) {
    //使用setnx命令。
    //不存在則保存返回1,加鎖成功。如果已經(jīng)存在則返回0,加鎖失敗。
    return SUCCESS.equals(jedis.setnx(key, requestId));
}

//刪除key的lua腳本,先比較requestId是否相等,相等則刪除
private static final String DEL_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

/**
  * 解鎖
  */
public boolean unLock(String key, String requestId) {
    //刪除成功表示解鎖成功
    Long result = (Long) jedis.eval(DEL_SCRIPT, Collections.singletonList(key), Collections.singletonList(requestId));
    return SUCCESS.equals(result);
}

上面代碼加鎖和解鎖的基本原理是:

【征服redis15】分布式鎖的功能與整體設(shè)計方案,精通redis,一個項目征服Java,分布式

3.2 問題一:增加超時機制,防止長期持有的情況

上面過程其實仍然是有問題的,上面的過程僅僅滿足上述的第一個條件和第三個條件,保證上鎖和解鎖都是同一個客戶端,也保證只有一個客戶端持有鎖。

但是第二點沒法保證,因為如果一個客戶端持有鎖的期間突然崩潰了,就會導(dǎo)致無法解鎖,最后導(dǎo)致出現(xiàn)死鎖的現(xiàn)象。

【征服redis15】分布式鎖的功能與整體設(shè)計方案,精通redis,一個項目征服Java,分布式

所以要有個超時的機制,在設(shè)置key的值時,需要加上有效時間,如果有效時間過期了,就會自動失效,就不會出現(xiàn)死鎖。然后加鎖的代碼就會變成這樣。

public boolean tryLock(String key, String requestId, int expireTime) {
    //使用jedis的api,保證原子性
    //NX 不存在則操作 EX 設(shè)置有效期,單位是秒
    String result = jedis.set(key, requestId, "NX", "EX", expireTime);
    //返回OK則表示加鎖成功
    return "OK".equals(result);
}

【征服redis15】分布式鎖的功能與整體設(shè)計方案,精通redis,一個項目征服Java,分布式

3.3 問題2:重入的問題

但是聰明的同學(xué)肯定會問,有效時間設(shè)置多長,假如我的業(yè)務(wù)操作比有效時間長,我的業(yè)務(wù)代碼還沒執(zhí)行完就自動給我解鎖了,不就完蛋了嗎。

這個問題就有點棘手了,在網(wǎng)上也有很多討論,第一種解決方法就是靠程序員自己去把握,預(yù)估一下業(yè)務(wù)代碼需要執(zhí)行的時間,然后設(shè)置有效期時間比執(zhí)行時間長一些,保證不會因為自動解鎖影響到客戶端業(yè)務(wù)代碼的執(zhí)行。

但是這并不是萬全之策,比如網(wǎng)絡(luò)抖動這種情況是無法預(yù)測的,也有可能導(dǎo)致業(yè)務(wù)代碼執(zhí)行的時間變長,所以并不安全。

有一種方法比較靠譜一點,就是給鎖續(xù)期。在Redisson框架實現(xiàn)分布式鎖的思路,就使用watchDog機制實現(xiàn)鎖的續(xù)期。當加鎖成功后,同時開啟守護線程,默認有效期是30秒,每隔10秒就會給鎖續(xù)期到30秒,只要持有鎖的客戶端沒有宕機,就能保證一直持有鎖,直到業(yè)務(wù)代碼執(zhí)行完畢由客戶端自己解鎖,如果宕機了自然就在有效期失效后自動解鎖。

【征服redis15】分布式鎖的功能與整體設(shè)計方案,精通redis,一個項目征服Java,分布式

但是聰明的同學(xué)可能又會問,你這個鎖只能加一次,不可重入??芍厝腈i意思是在外層使用鎖之后,內(nèi)層仍然可以使用,那么可重入鎖的實現(xiàn)思路又是怎么樣的呢?

在Redisson實現(xiàn)可重入鎖的思路,使用Redis的哈希表存儲可重入次數(shù),當加鎖成功后,使用hset命令,value(重入次數(shù))則是1。

"if (redis.call('exists', KEYS[1]) == 0) then " +
"redis.call('hset', KEYS[1], ARGV[2], 1); " +
"redis.call('pexpire', KEYS[1], ARGV[1]); " +
"return nil; " +
"end; "

如果同一個客戶端再次加鎖成功,則使用hincrby自增加一。?

"if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +
"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +
"redis.call('pexpire', KEYS[1], ARGV[1]); " +
"return nil; " +
"end; " +
"return redis.call('pttl', KEYS[1]);"

【征服redis15】分布式鎖的功能與整體設(shè)計方案,精通redis,一個項目征服Java,分布式

解鎖時,先判斷可重復(fù)次數(shù)是否大于0,大于0則減一,否則刪除鍵值,釋放鎖資源。

protected RFuture<Boolean> unlockInnerAsync(long threadId) {
    return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then " +
"return nil;" +
"end; " +
"local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); " +
"if (counter > 0) then " +
"redis.call('pexpire', KEYS[1], ARGV[2]); " +
"return 0; " +
"else " +
"redis.call('del', KEYS[1]); " +
"redis.call('publish', KEYS[2], ARGV[1]); " +
"return 1; "+
"end; " +
"return nil;",
Arrays.<Object>asList(getName(), getChannelName()), LockPubSub.UNLOCK_MESSAGE, internalLockLeaseTime, getLockName(threadId));
}

【征服redis15】分布式鎖的功能與整體設(shè)計方案,精通redis,一個項目征服Java,分布式

3.4 問題三:優(yōu)化輪詢加鎖的問題

上面的加鎖方法是加鎖后立即返回加鎖結(jié)果,如果加鎖失敗的情況下,總不可能一直輪詢嘗試加鎖,直到加鎖成功為止,這樣太過耗費性能。所以需要利用發(fā)布訂閱的機制進行優(yōu)化。

步驟如下:

  1. 當加鎖失敗后,訂閱鎖釋放的消息,自身進入阻塞狀態(tài)。
  2. 當持有鎖的客戶端釋放鎖的時候,發(fā)布鎖釋放的消息。
  3. 當進入阻塞等待的其他客戶端收到鎖釋放的消息后,解除阻塞等待狀態(tài),再次嘗試加鎖。

【征服redis15】分布式鎖的功能與整體設(shè)計方案,精通redis,一個項目征服Java,分布式

3.5?總結(jié)

以上的實現(xiàn)思路僅僅考慮在單機版Redis上,如果是集群版Redis需要考慮的問題還要再多一點。Redis由于他的高性能讀寫能力,所以在并發(fā)高的場景下使用Redis分布式鎖會多一點。

上面的問題一,二,三其實就是redis分布式鎖不斷改良發(fā)展的過程,第一個問題是設(shè)置有效期防止死鎖,并且引入守護線程給鎖續(xù)期,第二個問題是支持可重入鎖,第三個問題是加鎖失敗后阻塞等待,等鎖釋放后再次嘗試加鎖。Redisson框架解決這三個問題的思路也非常值得學(xué)習(xí)。

參考:阿里云開發(fā)者
?文章來源地址http://www.zghlxwxcb.cn/news/detail-815237.html

到了這里,關(guān)于【征服redis15】分布式鎖的功能與整體設(shè)計方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【面試題24】你是如何使用Redis分布式鎖的

    本文已收錄于PHP全棧系列專欄:PHP面試專區(qū)。 計劃將全覆蓋PHP開發(fā)領(lǐng)域所有的面試題, 對標資深工程師/架構(gòu)師序列 ,歡迎大家提前關(guān)注鎖定。 Redis分布式鎖是一種利用Redis實現(xiàn)的分布式鎖機制。它通過在共享的Redis實例上設(shè)置一個特定的鍵值對來實現(xiàn)對資源的互斥訪問。今

    2024年02月11日
    瀏覽(17)
  • 深入理解PHP+Redis實現(xiàn)分布式鎖的相關(guān)問題

    PHP使用分布式鎖,受語言本身的限制,有一些局限性。 通俗理解單機鎖問題:自家的鎖鎖自家的門,只能保證自家的事,管不了別人家不鎖門引發(fā)的問題,于是有了分布式鎖。 分布式鎖概念:是針對多個節(jié)點的鎖。避免出現(xiàn)數(shù)據(jù)不一致或者并發(fā)沖突的問題,讓每個節(jié)點確保

    2024年03月23日
    瀏覽(28)
  • Zookeeper 和 Redis 哪種更好? 為什么使用分布式鎖? 1. 利用 Redis 提供的 第二種,基于 ZK 實現(xiàn)分布式鎖的落地方案 對于 redis 的分布式鎖而言,它有以下缺點:

    關(guān)于這個問題,我們 可以從 3 個方面來說: 為什么使用分布式鎖? 使用分布式鎖的目的,是為了保證同一時間只有一個 JVM 進程可以對共享資源進行操作。 根據(jù)鎖的用途可以細分為以下兩類: 允許多個客戶端操作共享資源,我們稱為共享鎖 這種鎖的一般是對共享資源具有

    2024年01月16日
    瀏覽(23)
  • Redis實戰(zhàn)案例14-分布式鎖的基本原理、不同實現(xiàn)方法對比以及基于Redis進行實現(xiàn)思路

    Redis實戰(zhàn)案例14-分布式鎖的基本原理、不同實現(xiàn)方法對比以及基于Redis進行實現(xiàn)思路

    基于數(shù)據(jù)庫的分布式鎖:這種方式使用數(shù)據(jù)庫的特性來實現(xiàn)分布式鎖。具體流程如下: 獲取鎖:當一個節(jié)點需要獲得鎖時,它嘗試在數(shù)據(jù)庫中插入一個特定的唯一鍵值(如唯一約束的主鍵),如果插入成功,則表示獲得了鎖。 釋放鎖:當節(jié)點完成任務(wù)后,通過刪除該唯一鍵

    2024年02月13日
    瀏覽(49)
  • 分布式鎖原理與實戰(zhàn)三:ZooKeeper分布式鎖的原理

    分布式鎖原理與實戰(zhàn)三:ZooKeeper分布式鎖的原理

    ???????? 目錄 ZooKeeper分布式鎖的原理 ZooKeeper的每一個節(jié)點,都是一個天然的順序發(fā)號器。 ZooKeeper節(jié)點的遞增有序性,可以確保鎖的公平 ZooKeeper的節(jié)點監(jiān)聽機制,可以保障占有鎖的傳遞有序而且高效 ZooKeeper的節(jié)點監(jiān)聽機制,能避免羊群效應(yīng) 分布式鎖的搶占過程 客戶端

    2024年02月08日
    瀏覽(17)
  • 分布式鎖的產(chǎn)生以及使用

    分布式鎖的產(chǎn)生以及使用

    日常開發(fā)中,針對一些需要鎖定資源的操作,例如商城的訂單超賣問題、訂單重復(fù)提交問題等。 都是為了解決在資源有限的情況限制客戶端的訪問,對應(yīng)的是限流。 目前針對這種鎖資源的情況采取的往往是互斥鎖,例如 java 里的 synchronized 鎖以及?ReentrantLock,其中?synchroni

    2024年01月21日
    瀏覽(19)
  • 無分布式鎖的ID生成

    TEAM GARDEN 本來ID是自增的,后面發(fā)現(xiàn)自增ID比較麻煩,有問題: 不可控的間隔: 如果你在插入數(shù)據(jù)時,中途刪除了一些行,導(dǎo)致自增的ID出現(xiàn)間隔,那么新插入的行會填充這些間隔,可能會導(dǎo)致ID序列不連續(xù),不利于數(shù)據(jù)分析和理解。 不適用于批量插入: 在批量插入數(shù)據(jù)時,

    2024年02月11日
    瀏覽(23)
  • 分布式鎖的原子性問題

    4.6 分布式鎖的原子性問題 更為極端的誤刪邏輯說明: 線程1現(xiàn)在持有鎖之后,在執(zhí)行業(yè)務(wù)邏輯過程中,他正準備刪除鎖,而且已經(jīng)走到了條件判斷的過程中,比如他已經(jīng)拿到了當前這把鎖確實是屬于他自己的,正準備刪除鎖,但是此時他的鎖到期了,那么此時線程2進來,但

    2024年04月10日
    瀏覽(28)
  • 分布式鎖的幾種實現(xiàn)方式:

    redis是基于單線程,在某個時刻只會有一個線程執(zhí)行命令,可以利用set原子性的操作,配合set nx(RedisStringCommands.SetOption.SET_IF_ABSENT) ,這樣,當多個線程或多個節(jié)點嘗試獲取鎖時,只有一個可以成功,其他的會因為鎖已存在而獲取失敗。這種方式通過 Redis 來實現(xiàn)分布式鎖,

    2024年01月18日
    瀏覽(18)
  • Zookeeper分布式鎖的概念及原理

    Zookeeper分布式鎖的概念及原理

    分布式鎖的概念圖如下:一種演變過程。 在我們進行單機應(yīng)用程序開發(fā)時,往往會涉及到并發(fā)同步的問題,一般都會采用synchronized或者Lock鎖的方式來解決多線程間的代碼同步問題,這些多線程都是運行在同一個JVM之下,是沒有任何問題的。 場景:當有一個請求數(shù)據(jù)的線程進

    2024年02月12日
    瀏覽(84)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包