欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Redis分布式鎖及4種常見實(shí)現(xiàn)方法

 更新時(shí)間:2024年05月22日 11:24:48   作者:lcx_defender  
本文主要介紹了Redis分布式鎖及4種常見實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

線程鎖

主要用來給方法、代碼塊加鎖。當(dāng)某個方法或代碼使用鎖,在同一時(shí)刻僅有一個線程執(zhí)行該方法或該代碼段。線程鎖只在同一JVM中有效果,因?yàn)榫€程鎖的實(shí)現(xiàn)在根本上是依靠線程之間共享內(nèi)存實(shí)現(xiàn)的,比如Synchronized、Lock等。

進(jìn)程鎖

控制同一操作系統(tǒng)中多個進(jìn)程訪問某個共享資源,因?yàn)檫M(jìn)程具有獨(dú)立性,各個進(jìn)程無法訪問其他進(jìn)程的資源,因此無法通過synchronized等線程鎖實(shí)現(xiàn)進(jìn)程鎖

什么是分布式鎖

分布式鎖:滿足分布式系統(tǒng)或集群模式下多進(jìn)程可見并且互斥的鎖;一個方法在同一時(shí)間只能被一個機(jī)器的一個線程執(zhí)行。

分布式鎖應(yīng)具備的條件

  • 多進(jìn)程可見
  • 互斥
  • 高可用的獲取鎖與釋放鎖;
  • 高性能的獲取鎖與釋放鎖;
  • 具備鎖失效機(jī)制,防止死鎖;
  • 具備可重入特性;
  • 具備非阻塞鎖特性,即沒有獲取到鎖將直接返回獲取鎖失??;

分布式鎖常見的實(shí)現(xiàn)方式

基于Mysql

在數(shù)據(jù)庫中創(chuàng)建一個表,表中包含方法名等字段,并在方法名name字段上創(chuàng)建唯一索引,想要執(zhí)行某個方法,就使用這個方法名向表中插入一條記錄,成功插入則獲取鎖,刪除對應(yīng)的行就是鎖釋放。

CREATE TABLE `method_lock` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `method_name` varchar(64) NOT NULL COMMENT '鎖定的方法名',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uidx_method_name` (`method_name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='鎖定中的方法';

這里主要是用method_name字段作為唯一索引來實(shí)現(xiàn),唯一索引保證了該記錄的唯一性,鎖釋放就直接刪掉該條記錄就行了。

INSERT INTO method_lock (method_name) VALUES ('methodName');
delete from method_lock where method_name ='methodName';

缺點(diǎn)

1、因?yàn)槭腔跀?shù)據(jù)庫實(shí)現(xiàn)的,數(shù)據(jù)庫的可用性和性能將直接影響分布式鎖的可用性及性能。高并發(fā)狀態(tài)下,數(shù)據(jù)庫讀寫效率一般都非常緩慢。所以,數(shù)據(jù)庫需要雙機(jī)部署、數(shù)據(jù)同步、主備切換;

2、不具備可重入的特性,因?yàn)橥粋€線程在釋放鎖之前,行數(shù)據(jù)一直存在,無法再次成功插入數(shù)據(jù),所以,需要在表中新增一列,用于記錄當(dāng)前獲取到鎖的機(jī)器和線程信息,在再次獲取鎖的時(shí)候,先查詢表中機(jī)器和線程信息是否和當(dāng)前機(jī)器和線程相同,若相同則直接獲取鎖;

3、沒有鎖失效機(jī)制,因?yàn)橛锌赡艹霈F(xiàn)成功插入數(shù)據(jù)后,服務(wù)器宕機(jī)了,對應(yīng)的數(shù)據(jù)沒有被刪除,當(dāng)服務(wù)恢復(fù)后一直獲取不到鎖。所以,需要在表中新增一列,用于記錄失效時(shí)間,并且需要有定時(shí)任務(wù)清除這些失效的數(shù)據(jù);

4、不具備阻塞鎖特性,獲取不到鎖直接返回失敗,所以需要優(yōu)化獲取邏輯,循環(huán)多次去獲取。

5、在實(shí)施的過程中會遇到各種不同的問題,為了解決這些問題,實(shí)現(xiàn)方式將會越來越復(fù)雜;依賴數(shù)據(jù)庫需要一定的資源開銷,性能問題需要考慮。

基于Redis分布式鎖

獲取鎖

利用setnx這種互斥命令,利用鎖超時(shí)時(shí)間進(jìn)行到期釋放避免死鎖,且Redis具有高可用高性能等特點(diǎn)及優(yōu)勢。

Redis 的分布式鎖, setnx 命令并設(shè)置過期時(shí)間就行嗎?

setnx [key] [value] 
expire [key] 30

雖然setnx是原子性的,但是setnx + expire就不是了,也就是說setnx和expire是分兩步執(zhí)行的,【加鎖和超時(shí)】兩個操作是分開的,如果expire執(zhí)行失敗了,那么鎖同樣得不到釋放。

獲取鎖的原子性問題

# 設(shè)置某個 key 的值并設(shè)置多少毫秒或秒 過期
set <key> <value> PX <多少毫秒> NX
或
set <key> <value> EX <多少秒> NX
# 設(shè)置一個鍵為lock,值為thread,ex表示以秒為單位,px以微秒為單位,nx表示不存在該key的時(shí)候才能設(shè)置
set lock thread1 nx ex 10

當(dāng)且僅當(dāng)key值lock不存在時(shí),set一個key為lock,val為thread1的字符串,返回1;若key存在,則什么都不做,返回0。

Java的實(shí)現(xiàn)

	public boolean tryLock(long timeoutSec) {
        // 獲取線程標(biāo)識,ID_PREFIX為
        String threadId = ID_PREFIX +  Thread.currentThread().getId();
        // 獲取鎖,name為自定義的業(yè)務(wù)名稱
        Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(success);
    }

釋放鎖

  • 手動釋放
# 將對應(yīng)的鍵刪除即可
del [key]
  • 超時(shí)釋放

釋放錯誤的鎖

假設(shè)如下三個線程是同一個用戶的業(yè)務(wù)線程,即假設(shè)線程1、線程2、線程3申請的分布式鎖key一樣:

  • 線程1獲取成功了一個分布式鎖,由于一些問題,線程1執(zhí)行超時(shí)了,分布式鎖被超期釋放。
  • 在鎖釋放后,有一個線程2又來獲取鎖,并且成功。
  • 在線程2執(zhí)行過程中,線程1運(yùn)行結(jié)束,由于不知道自己鎖已經(jīng)被超期釋放,所以它直接手動釋放鎖,錯誤的釋放了線程2的鎖。
  • 這時(shí)如果又有一個線程3前來獲取鎖,就能獲取成功;而線程2此時(shí)也持有鎖。

所以,設(shè)置鎖的過期時(shí)間時(shí),還需要設(shè)置唯一編號。在編程實(shí)現(xiàn)釋放鎖的時(shí)候,需要判斷當(dāng)前釋放的鎖的值是否與之前的一致;若一致,則刪除;不一致,則不操作。

代碼示例:

	public void unlock() {
        // 獲取線程標(biāo)識
        String threadId = ID_PREFIX +  Thread.currentThread().getId();
        // 獲取鎖中的標(biāo)識
        String id = stringRedisTemplate.opsForValue().get(KEY_PREFIX + name);
        // 判斷標(biāo)識是否一致
        if (threadId.equals(id)) {
            // 釋放鎖
            stringRedisTemplate.delete(KEY_PREFIX + name);
        }
    }

刪除鎖的原子性問題

  • 線程1在時(shí)限內(nèi)完成了業(yè)務(wù),它開始執(zhí)行刪除鎖的操作。
  • 線程1判斷完當(dāng)前鎖的標(biāo)識(對應(yīng)的value)一樣后,由于一些問題,線程1被阻塞,該key超期被刪除了
  • 線程2過來申請分布式鎖,并且成功
  • 此時(shí),線程1才正式對分布式鎖執(zhí)行刪除,由于可能是同一個用戶的業(yè)務(wù)線程,線程1與線程2的申請的分布式鎖key一樣,所以線程1調(diào)用的刪除鎖操作將線程2的鎖刪掉了(悲!故技重施?。?hellip;

所以,我們還得確保獲取和刪除操作之間的原子性??梢越柚鶯ua腳本保證原子性,釋放鎖的核心邏輯【GET、判斷、DEL】,寫成 Lua 腳本,讓Redis調(diào)用。

使用Lua腳本改進(jìn)Redis釋放分布式鎖

Lua中Redis的調(diào)用函數(shù)

redis.call('命令名稱','key','其他參數(shù)',...)

比如我們執(zhí)行set name jack命令,可以使用:

redis.call('set','name','jack')

使用Redis調(diào)用Lua腳本

調(diào)用方法

# script腳本語句;numkeys腳本需要的key類型的參數(shù)個數(shù)
eval script numkeys key [key ...] arg [arg ...]

例如,執(zhí)行redis.call('set', 'name', 'Jack')腳本設(shè)置redis鍵值,語法如下:

eval "return redis.call('set', 'name', 'Jack')" 0

如果key和value不想寫死,可以使用如下格式

eval "return redis.call('set', KEYS[1], ARGV[1])" 1 name Jack

Lua中,數(shù)組下標(biāo)從1開始,此處1標(biāo)識只有一個key類型的參數(shù),其他參數(shù)都會放入ARGV數(shù)組。在腳本中,可以通過KEYS數(shù)組和ARGV數(shù)組獲取參數(shù)

Lua腳本(unlock.lua)

if(redis.call('get', KEYS[1]) == ARGV[1]) then
    return redis.call('del', KEYS[1])
end
return 0

參考完整代碼

import cn.hutool.core.lang.UUID;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;

import java.util.Collections;
import java.util.concurrent.TimeUnit;

public class SimpleRedisLock {
    private String name;
    private StringRedisTemplate stringRedisTemplate;
    private static final String KEY_PREFIX = "lock:";
    private static final String ID_PREFIX = UUID.randomUUID().toString(true) + "-";
    // 加載腳本
    private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;

    static {
        UNLOCK_SCRIPT = new DefaultRedisScript<>();
        // 加載工程resourcecs下的unlock.lua文件
        UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));
        UNLOCK_SCRIPT.setResultType(Long.class);
    }
    public SimpleRedisLock(String name, StringRedisTemplate stringRedisTemplate) {
        this.name = name;
        this.stringRedisTemplate = stringRedisTemplate;
    }
    
    public boolean tryLock(long timeoutSec) {
        // 獲取線程標(biāo)識
        String threadId = ID_PREFIX +  Thread.currentThread().getId();
        // 獲取鎖
        Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(success);
    }

    public void unlock() {
        // 調(diào)用Lua腳本
        stringRedisTemplate.execute(UNLOCK_SCRIPT,
                Collections.singletonList(KEY_PREFIX + name),
                ID_PREFIX +  Thread.currentThread().getId());
    }
}

業(yè)務(wù)調(diào)用使用方法

	/**
	* 業(yè)務(wù)service導(dǎo)入
	*/
	@Resource
    private RedissonClient redissonClient;

	/** 
	* 業(yè)務(wù)方法內(nèi)
	*/
	SimpleRedisLock lock = new SimpleRedisLock("order:" + userId, stringRedisTemplate);
	// 創(chuàng)建鎖對象
    RLock lock = redissonClient.getLock("lock:order:" + userId);
    // 嘗試獲取鎖
    boolean isLock = lock.tryLock();
    // 判斷是否成功
    if (!isLock) {
    	// 獲取失敗
        return Result.fail("不允許重復(fù)下單");
    }
	try {
    	// 需要鎖執(zhí)行的業(yè)務(wù)代碼部分
    } finally {
        // 釋放鎖
        lock.unlock();
    }

當(dāng)前還存在的問題

  • 不可重入:同一個線程無法多次獲取同一把鎖(線程1在執(zhí)行方法1的時(shí)候調(diào)用了方法2,而方法2也需要鎖)
  • 不可重試:獲取鎖只嘗試一次就返回false,沒有重試機(jī)制;當(dāng)前直接返回結(jié)果。
  • 超時(shí)釋放:鎖超時(shí)釋放雖然可以避免死鎖,但是如果業(yè)務(wù)執(zhí)行耗時(shí)較長,也會導(dǎo)致鎖釋放,存在安全隱患。
  • 主從一致性:如果redis提供了主從集群,主存同步存在延遲。當(dāng)主結(jié)點(diǎn)宕機(jī)時(shí),從節(jié)點(diǎn)尚未同步主結(jié)點(diǎn)鎖數(shù)據(jù),則會造成鎖失效。

Redisson框架中就實(shí)現(xiàn)了WatchDog(看門狗),加鎖時(shí)沒有指定加鎖時(shí)間時(shí)會啟用 watchdog 機(jī)制,默認(rèn)加鎖 30 秒,每 10 秒鐘檢查一次,如果存在就重新設(shè)置過期時(shí)間。

RedLock應(yīng)對主從一致性問題

Redis 的作者提出一種解決方案 Redlock ,基于多個 Redis 節(jié)點(diǎn),不再需要部署從庫和哨兵實(shí)例,只部署主庫。但主庫要部署多個,官方推薦至少 5 個實(shí)例。

流程:

  • Client先獲取「當(dāng)前時(shí)間戳T1」

  • Client依次向這 5 個 Redis 實(shí)例發(fā)起加鎖請求(用前面講到的 SET 命令),且每個請求會設(shè)置超時(shí)時(shí)間(毫秒級,要遠(yuǎn)小于鎖的有效時(shí)間),如果某一個實(shí)例加鎖失?。òňW(wǎng)絡(luò)超時(shí)、鎖被其它人持有等各種異常情況),就立即向下一個 Redis 實(shí)例申請加鎖

  • 如果Client從 >=3 個(大多數(shù))以上 Redis 實(shí)例加鎖成功,則再次獲取「當(dāng)前時(shí)間戳T2」,如果 T2 - T1 < 鎖的過期時(shí)間,此時(shí),認(rèn)為客戶端加鎖成功,否則認(rèn)為加鎖失敗

  • 加鎖成功,去操作共享資源(例如修改 MySQL 某一行,或發(fā)起一個 API 請求)

  • 加鎖失敗,Client向「全部節(jié)點(diǎn)」發(fā)起釋放鎖請求(前面講到的 Lua 腳本釋放鎖)

為什么要向多個Redis申請鎖?

向多臺Redis申請鎖,即使部分服務(wù)器異常宕機(jī),剩余的Redis加鎖成功,整個鎖服務(wù)依舊可用。

為什么步驟 3 加鎖成功后,還要計(jì)算加鎖的累計(jì)耗時(shí)?

加鎖操作的針對的是分布式中的多個節(jié)點(diǎn),所以耗時(shí)肯定是比單個實(shí)例耗時(shí)更,還要考慮網(wǎng)絡(luò)延遲、丟包、超時(shí)等情況發(fā)生,網(wǎng)絡(luò)請求次數(shù)越多,異常的概率越大。
所以即使 N/2+1 個節(jié)點(diǎn)加鎖成功,但如果加鎖的累計(jì)耗時(shí)已經(jīng)超過了鎖的過期時(shí)間,那么此時(shí)的鎖已經(jīng)沒有意義了

釋放鎖操作為什么要針對所有結(jié)點(diǎn)?

為了清除干凈所有的鎖。在之前申請鎖的操作過程中,鎖雖然已經(jīng)加在Redis上,但是在獲取結(jié)果的時(shí)候,出現(xiàn)網(wǎng)絡(luò)等方面的問題,導(dǎo)致顯示失敗。所以在釋放鎖的時(shí)候,不管以前有沒有加鎖成功,都要釋放所有節(jié)點(diǎn)相關(guān)鎖。

Zookeeper

ZooKeeper 的數(shù)據(jù)存儲結(jié)構(gòu)就像一棵樹,這棵樹由節(jié)點(diǎn)組成,這種節(jié)點(diǎn)叫做 Znode。

  • Client嘗試創(chuàng)建一個 znode 節(jié)點(diǎn),比如/lock,比如Client1先到達(dá)就創(chuàng)建成功了,相當(dāng)于拿到了鎖

  • 其它的客戶端會創(chuàng)建失?。▃node 已存在),獲取鎖失敗。

  • Client2可以進(jìn)入一種等待狀態(tài),等待當(dāng)/lock 節(jié)點(diǎn)被刪除的時(shí)候,ZooKeeper 通過 watch 機(jī)制通知它

  • 持有鎖的Client1訪問共享資源完成后,將 znode 刪掉,鎖釋放掉了

  • Client2繼續(xù)完成獲取鎖操作,直到獲取到鎖為止

ZooKeeper不需要考慮過期時(shí)間,而是用【臨時(shí)節(jié)點(diǎn)】,Client拿到鎖之后,只要連接不斷,就會一直持有鎖。即使Client崩潰,相應(yīng)臨時(shí)節(jié)點(diǎn)Znode也會自動刪除,保證了鎖釋放。

Zookeeper 是檢測客戶端是否崩潰

每個客戶端都與 ZooKeeper 維護(hù)著一個 Session,這個 Session 依賴定期的心跳(heartbeat)來維持。

如果 Zookeeper 長時(shí)間收不到客戶端的心跳,就認(rèn)為這個 Session 過期了,也會把這個臨時(shí)節(jié)點(diǎn)刪除。

當(dāng)然這也并不是完美的解決方案

以下場景中Client1和Client2在窗口時(shí)間內(nèi)可能同時(shí)獲得鎖:

  • Client 1 創(chuàng)建了 znode 節(jié)點(diǎn)/lock,獲得了鎖。

  • Client 1 進(jìn)入了長時(shí)間的 GC pause。(或者網(wǎng)絡(luò)出現(xiàn)問題、或者 zk 服務(wù)檢測心跳線程出現(xiàn)問題等等)

  • Client 1 連接到 ZooKeeper 的 Session 過期了。znode 節(jié)點(diǎn)/lock 被自動刪除。

  • Client 2 創(chuàng)建了 znode 節(jié)點(diǎn)/lock,從而獲得了鎖。

  • Client 1 從 GC pause 中恢復(fù)過來,它仍然認(rèn)為自己持有鎖。

Zookeeper 的優(yōu)點(diǎn)

  • 不需要考慮鎖的過期時(shí)間,使用起來比較方便

  • watch 機(jī)制,加鎖失敗,可以 watch 等待鎖釋放,實(shí)現(xiàn)樂觀鎖

Zookeeper 的缺點(diǎn)

  • 性能不如 Redis

  • 部署和運(yùn)維成本高

  • 客戶端與 Zookeeper 的長時(shí)間失聯(lián),鎖被釋放問題

Etcd

Etcd是一個Go語言實(shí)現(xiàn)的非??煽康膋v存儲系統(tǒng),常在分布式系統(tǒng)中存儲著關(guān)鍵的數(shù)據(jù),通常應(yīng)用在配置中心、服務(wù)發(fā)現(xiàn)與注冊、分布式鎖等場景。

Etcd特性

  • Lease機(jī)制:即租約機(jī)制(TTL,Time To Live),etcd可以為存儲的kv對設(shè)置租約,當(dāng)租約到期,kv將失效刪除;同時(shí)也支持續(xù)約,keepalive
  • Revision機(jī)制:每個key帶有一個Revision屬性值,etcd每進(jìn)行一次事務(wù)對應(yīng)的全局Revision值都會+1,因此每個key對應(yīng)的Revision屬性值都是全局唯一的。通過比較Revision的大小就可以知道進(jìn)行寫操作的順序
  • 在實(shí)現(xiàn)分布式鎖時(shí),多個程序同時(shí)搶鎖,根據(jù)Revision值大小依次獲得鎖,避免“驚群效應(yīng)”,實(shí)現(xiàn)公平鎖
  • Prefix機(jī)制:也稱為目錄機(jī)制,可以根據(jù)前綴獲得該目錄下所有的key及其對應(yīng)的屬性值
  • Watch機(jī)制:watch支持watch某個固定的key或者一個前綴目錄,當(dāng)watch的key發(fā)生變化,客戶端將收到通知

滿足分布式鎖的特性:

  • 租約機(jī)制(Lease):用于支撐異常情況下的鎖自動釋放能力
  • 前綴和 Revision 機(jī)制:用于支撐公平獲取鎖和排隊(duì)等待的能力
  • 監(jiān)聽機(jī)制(Watch):用于支撐搶鎖能力
  • 集群模式:用于支撐鎖服務(wù)的高可用
func main() {
    config := clientv3.Config{
        Endpoints:   []string{"xxx.xxx.xxx.xxx:2379"},
        DialTimeout: 5 * time.Second,
    }
 
    // 獲取客戶端連接
    client, err := clientv3.New(config)
    if err != nil {
        fmt.Println(err)
        return
    }
 
    // 1. 上鎖(創(chuàng)建租約,自動續(xù)租,拿著租約去搶占一個key )
    // 用于申請租約
    lease := clientv3.NewLease(client)
 
    // 申請一個10s的租約
    leaseGrantResp, err := lease.Grant(context.TODO(), 10) //10s
    if err != nil {
        fmt.Println(err)
        return
    }
 
    // 拿到租約的id
    leaseID := leaseGrantResp.ID
 
    // 準(zhǔn)備一個用于取消續(xù)租的context
    ctx, cancelFunc := context.WithCancel(context.TODO())
 
    // 確保函數(shù)退出后,自動續(xù)租會停止
    defer cancelFunc()
        // 確保函數(shù)退出后,租約會失效
    defer lease.Revoke(context.TODO(), leaseID)
 
    // 自動續(xù)租
    keepRespChan, err := lease.KeepAlive(ctx, leaseID)
    if err != nil {
        fmt.Println(err)
        return
    }
 
    // 處理續(xù)租應(yīng)答的協(xié)程
    go func() {
        select {
        case keepResp := <-keepRespChan:
            if keepRespChan == nil {
                fmt.Println("lease has expired")
                goto END
            } else {
                // 每秒會續(xù)租一次
                fmt.Println("收到自動續(xù)租應(yīng)答", keepResp.ID)
            }
        }
    END:
    }()
 
    // if key 不存在,then設(shè)置它,else搶鎖失敗
    kv := clientv3.NewKV(client)
    // 創(chuàng)建事務(wù)
    txn := kv.Txn(context.TODO())
    // 如果key不存在
    txn.If(clientv3.Compare(clientv3.CreateRevision("/cron/lock/job7"), "=", 0)).
        Then(clientv3.OpPut("/cron/jobs/job7", "", clientv3.WithLease(leaseID))).
        Else(clientv3.OpGet("/cron/jobs/job7")) //如果key存在
 
    // 提交事務(wù)
    txnResp, err := txn.Commit()
    if err != nil {
        fmt.Println(err)
        return
    }
 
    // 判斷是否搶到了鎖
    if !txnResp.Succeeded {
        fmt.Println("鎖被占用了:", string(txnResp.Responses[0].GetResponseRange().Kvs[0].Value))
        return
    }
 
    // 2. 處理業(yè)務(wù)(鎖內(nèi),很安全)
 
    fmt.Println("處理任務(wù)")
    time.Sleep(5 * time.Second)
 
    // 3. 釋放鎖(取消自動續(xù)租,釋放租約)
    // defer會取消續(xù)租,釋放鎖
}

clientv3提供的concurrency包也實(shí)現(xiàn)了分布式鎖

  • 首先concurrency.NewSession方法創(chuàng)建Session對象
  • 然后Session對象通過concurrency.NewMutex 創(chuàng)建了一個Mutex對象
  • 加鎖和釋放鎖分別調(diào)用Lock和UnLock

筆記Zookeeper和Etcd部分參考:https://mp.weixin.qq.com/s/wL9MRnx8HVXNFOt6ZTWELw

到此這篇關(guān)于Redis分布式鎖及4種常見實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)Redis分布式鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis中有序集合的內(nèi)部實(shí)現(xiàn)方式的詳細(xì)介紹

    Redis中有序集合的內(nèi)部實(shí)現(xiàn)方式的詳細(xì)介紹

    本文主要介紹了Redis中有序集合的內(nèi)部實(shí)現(xiàn)方式的詳細(xì)介紹,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • redis中Could not get a resource from the pool異常及解決方案

    redis中Could not get a resource from

    這篇文章主要介紹了redis中Could not get a resource from the pool異常及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 使用Redis實(shí)現(xiàn)UA池的方案

    使用Redis實(shí)現(xiàn)UA池的方案

    這篇文章主要介紹了使用Redis實(shí)現(xiàn)UA池的方案,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-11-11
  • 一篇文章帶你徹底搞懂Redis?事務(wù)

    一篇文章帶你徹底搞懂Redis?事務(wù)

    這篇文章主要介紹了一篇文章帶你徹底搞懂Redis?事務(wù)的相關(guān)資料,需要的朋友可以參考下
    2022-10-10
  • redis發(fā)布訂閱_動力節(jié)點(diǎn)Java學(xué)院整理

    redis發(fā)布訂閱_動力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了redis發(fā)布訂閱,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • 詳解redis分布式鎖(優(yōu)化redis分布式鎖的過程及Redisson使用)

    詳解redis分布式鎖(優(yōu)化redis分布式鎖的過程及Redisson使用)

    在分布式的開發(fā)中,以電商庫存的更新功能進(jìn)行講解,在實(shí)際的應(yīng)用中相同功能的消費(fèi)者是有多個的,這篇文章主要介紹了redis分布式鎖詳解(優(yōu)化redis分布式鎖的過程及Redisson使用),需要的朋友可以參考下
    2021-11-11
  • redis主從連接不成功錯誤問題及解決

    redis主從連接不成功錯誤問題及解決

    這篇文章主要介紹了redis主從連接不成功錯誤問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教<BR>
    2024-01-01
  • 基于Redission的分布式鎖實(shí)戰(zhàn)

    基于Redission的分布式鎖實(shí)戰(zhàn)

    本文主要介紹了基于Redission的分布式鎖實(shí)戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • redis實(shí)現(xiàn)主從模式(1主2從)

    redis實(shí)現(xiàn)主從模式(1主2從)

    本文主要介紹了在Windows環(huán)境下搭建和測試Redis的主從復(fù)制模式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-12-12
  • Redis過期數(shù)據(jù)是否會被立馬刪除

    Redis過期數(shù)據(jù)是否會被立馬刪除

    這篇文章主要為大家介紹了Redis過期數(shù)據(jù)會被立馬刪除么的問題解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07

最新評論