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

Redis分布式鎖之紅鎖的實(shí)現(xiàn)

 更新時(shí)間:2023年12月20日 10:54:25   作者:懶鳥(niǎo)一枚  
在Redis中,紅鎖是一種分布式鎖的實(shí)現(xiàn)機(jī)制,旨在解決多個(gè)客戶(hù)端在分布式環(huán)境中對(duì)共享資源進(jìn)行并發(fā)訪(fǎng)問(wèn)的問(wèn)題,本文主要介紹了Redis分布式鎖之紅鎖的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下

一 分布式鎖的概念

1:概念

分布式鎖(多服務(wù)共享鎖) 在分布式的部署環(huán)境下,通過(guò)鎖機(jī)制來(lái)讓多客戶(hù)端互斥的對(duì)共享資源進(jìn)行訪(fǎng)問(wèn)控制分布式系統(tǒng)不同進(jìn)程共同訪(fǎng)問(wèn)共享資源的一種鎖的實(shí)現(xiàn)。如果不同的系統(tǒng)或同一個(gè)系統(tǒng)的不同主機(jī)之間共享了某個(gè)臨界資源,往往需要互斥來(lái)防止彼此干擾,以保證一致性。

2:鎖/分布式鎖/事務(wù)區(qū)別

  • 鎖 單進(jìn)程的系統(tǒng)中,存在多線(xiàn)程同時(shí)操作一個(gè)公共變量,此時(shí)需要加鎖對(duì)變量進(jìn)行同步操作,保證多線(xiàn)程的操作線(xiàn)性執(zhí)行消除并發(fā)修改。解決的是單進(jìn)程中的多線(xiàn)程并發(fā)問(wèn)題。
  • 分布式鎖 只要的應(yīng)用場(chǎng)景是在集群模式的多個(gè)相同服務(wù),可能會(huì)部署在不同機(jī)器上,解決進(jìn)程間安全問(wèn)題,防止多進(jìn)程同時(shí)操作一個(gè)變量或者數(shù)據(jù)庫(kù)。解決的是多進(jìn)程的并發(fā)問(wèn)題 事務(wù) 解決一個(gè)會(huì)話(huà)過(guò)程中,上下文的修改對(duì)所有數(shù)據(jù)庫(kù)表的操作要么全部成功,要不全部失敗。所以應(yīng)用在service層。解決的是一個(gè)會(huì)話(huà)中的操作的數(shù)據(jù)一致性。
  • 分布式事務(wù) 解決一個(gè)聯(lián)動(dòng)操作,比如一個(gè)商品的買(mǎi)賣(mài)分為添加商品到購(gòu)物車(chē)、修改商品庫(kù)存,此時(shí)購(gòu)物車(chē)服務(wù)和商品庫(kù)存服務(wù)可能部署在兩臺(tái)電腦,這時(shí)候需要保證對(duì)兩個(gè)服務(wù)的操作都全部成功或者全部回退。解決的是組合服務(wù)的數(shù)據(jù)操作的一致性問(wèn)題

3:reddison的公平鎖

reddison公平鎖枷鎖

默認(rèn)的加鎖邏輯是非公平的。在加鎖失敗時(shí),線(xiàn)程會(huì)進(jìn)入 while 循環(huán),一直嘗試獲得鎖,這時(shí)候是多線(xiàn)程進(jìn)行競(jìng)爭(zhēng)。就是說(shuō)誰(shuí)搶到就是誰(shuí)的。Redisson 提供了公平鎖機(jī)制,使用方式如下

RLock fairLock = redisson.getFairLock("anyLock");
// 最常見(jiàn)的使用方法
fairLock.lock();

看門(mén)狗機(jī)制是在 RedissonBaseLock#scheduleExpirationRenewal 方法中,這塊公平鎖和非公平鎖并無(wú)區(qū)別。前文已經(jīng)了解到,公平鎖加鎖失敗之后,會(huì)將當(dāng)前放到等待隊(duì)列中,通過(guò) Java 代碼中的循環(huán)不斷嘗試獲得鎖。

reddison公平鎖釋放

公平鎖的釋放同樣分為主動(dòng)釋放和超時(shí)釋放。

  • 主動(dòng)釋放,即自己調(diào)用釋放鎖。
  • 超時(shí)刪除,則分為兩種,一種是持鎖線(xiàn)程超時(shí)刪除,這種和非公平鎖沒(méi)有任何區(qū)別,因?yàn)檫@個(gè)鎖也是含有超時(shí)時(shí)間+看門(mén)狗續(xù)租的。另一種則是等待隊(duì)列中的超時(shí)刪除,是在每次獲取鎖之前,判斷第一個(gè)等待線(xiàn)程的時(shí)間戳是否超時(shí),從而移除鎖。

二 、使用的案例場(chǎng)景

需求當(dāng)在打車(chē)軟件中,乘客下了訂單。多個(gè)司機(jī)搶單,此時(shí)因?yàn)閱巫又挥幸粋€(gè),多個(gè)司機(jī)對(duì)此共享資源進(jìn)行搶?zhuān)颂帒?yīng)該使用分布式鎖;后臺(tái)服務(wù)部署在多臺(tái)服務(wù)器上;
controller層代碼

 @GetMapping("/do/{orderId}")
    public String grab(@PathVariable("orderId") int orderId, int driverId){
        System.out.println("order:"+orderId+",driverId:"+driverId);
        //此處調(diào)用鎖控制層代碼
        grabService.grabOrder(orderId,driverId);
        return "";
    }

鎖控制層代碼(使用synchronized 不成功)使用synchronized 不能保證多臺(tái)服務(wù)器只有一個(gè)搶成功;因?yàn)閟ynchronized 只能鎖本服務(wù)的資源;多臺(tái)服務(wù)的資源是鎖不住的;

@Autowired
	OrderService orderService;
	
	@Override
	public String grabOrder(int orderId, int driverId) {
		String lock = (orderId+"");
		
		synchronized (lock.intern()) {
			try {
				System.out.println("司機(jī):"+driverId+" 執(zhí)行搶單邏輯");
				//此處調(diào)用訂單業(yè)務(wù)代碼
	            boolean b = orderService.grab(orderId, driverId);
	            if(b) {
	            	System.out.println("司機(jī):"+driverId+" 搶單成功");
	            }else {
	            	System.out.println("司機(jī):"+driverId+" 搶單失敗");
	            }
	            
	        } finally {
	        	
	            
	        }
		}
		
		
		return null;
	}

調(diào)用的訂單業(yè)務(wù)代碼這一層就是寫(xiě)的偽代碼,后續(xù)并不關(guān)注他

在這里插入圖片描述

三、Redis解決方案-紅鎖

介紹

紅鎖本質(zhì)上就是使用多個(gè)Redis做鎖。例如有5個(gè)Redis,一次鎖的獲取,會(huì)對(duì)每個(gè)請(qǐng)求都獲取一遍,如果獲取鎖成功的數(shù)量超過(guò)一半(2.5),則獲取鎖成功,反之失??;
釋放鎖也需要對(duì)每個(gè)Redis釋放

紅鎖原理

  • 在Redis的分布式環(huán)境中,我們假設(shè)有5個(gè)Redis master。這些節(jié)點(diǎn)完全互相獨(dú)立,沒(méi)有主從關(guān)系
  • 線(xiàn)程1向這5個(gè)redis加鎖,當(dāng)加到第三個(gè)的時(shí)候,4和5加不上了;但是符合紅鎖的n/2+1原則,所以線(xiàn)程1獲取到了鎖;
  • 當(dāng)redis3掛了,此時(shí)線(xiàn)程1獲取到了鎖,正在順序執(zhí)行,
  • 線(xiàn)程2來(lái)到了redis搶占鎖,因?yàn)?掛了,1,2有鎖,只有4和5可以加鎖,因?yàn)槲覀冏?cè)的時(shí)候是5臺(tái),4和5這兩臺(tái)不滿(mǎn)足n/2+1原則,搶占鎖失?。?/li>

當(dāng)鎖遇到故障轉(zhuǎn)移

單實(shí)例肯定不是很可靠吧?加鎖成功之后,結(jié)果 Redis 服務(wù)宕機(jī)了,這不就涼涼~
這時(shí)候會(huì)提出來(lái)將 Redis 主從部署。即使是主從,也是存在巧合的!
主從結(jié)構(gòu)中存在明顯的競(jìng)態(tài):

客戶(hù)端 A 從 master 獲取到鎖在 master 將鎖同步到 slave 之前,master 宕掉了。
slave 節(jié)點(diǎn)被晉級(jí)為 master 節(jié)點(diǎn)客戶(hù)端 B 取得了同一個(gè)資源被客戶(hù)端 A 已經(jīng)獲取到的另外一個(gè)鎖。安全失效!有時(shí)候程序就是這么巧,比如說(shuō)正好一個(gè)節(jié)點(diǎn)掛掉的時(shí)候,多個(gè)客戶(hù)端同時(shí)取到了鎖。如果你可以接受這種小概率錯(cuò)誤,那用這個(gè)基于復(fù)制的方案就完全沒(méi)有問(wèn)題。
那我使用集群呢?如果還記得前面的內(nèi)容,應(yīng)該是知道對(duì)集群進(jìn)行加鎖的時(shí)候,其實(shí)是通過(guò) CRC16 的 hash 函數(shù)來(lái)對(duì) key 進(jìn)行取模,將結(jié)果路由到預(yù)先分配過(guò) slot 的相應(yīng)節(jié)點(diǎn)上。
發(fā)現(xiàn)其實(shí)還是發(fā)到單個(gè)節(jié)點(diǎn)上的
! 這時(shí)候 Redis 作者提出了 RedLock 的概念

在這里插入圖片描述

總結(jié)一下就是對(duì)集群的每個(gè)節(jié)點(diǎn)進(jìn)行加鎖,如果大多數(shù)(N/2+1)加鎖成功了,則認(rèn)為獲取鎖成功。

RedLock 的問(wèn)題
看著 RedLock 好像是解決問(wèn)題了:

客戶(hù)端 A 鎖住了集群的大多數(shù)(一半以上);
客戶(hù)端 B 也要鎖住大多數(shù);
這里肯定會(huì)沖突,所以 客戶(hù)端 B 加鎖失敗。
那實(shí)際解決問(wèn)題了么?

加鎖 key 的問(wèn)題

有一個(gè)很大的疑問(wèn),我加鎖 lock1、lock2、lock3,但是 RedissonRedLock 是如何保證這三個(gè) key 是在歸屬于 Redis 集群中不同的 master 呢?因?yàn)榘凑?RedLock 的理論,是需要在半數(shù)以上的 master 節(jié)點(diǎn)加鎖成功。閱讀完源碼之后,發(fā)現(xiàn) RedissonRedLock 完全是 RedissonMultiLock 的子類(lèi),只是重寫(xiě)了 failedLocksLimit 方法,保證半數(shù)以上加鎖成功即可。所以這三個(gè) key,是需要用戶(hù)來(lái)保證分散在不同的節(jié)點(diǎn)上的。

紅鎖的爭(zhēng)議

那我使用 5 個(gè)單節(jié)點(diǎn)的客戶(hù)端,然后再使用紅鎖,聽(tīng)著好像是可以的,并且 RedissonRedLock 可以這樣使用。但是那和 Redis 集群還有啥關(guān)系??!所以依然沒(méi)有解決我的問(wèn)題,在 redis 集群下 針對(duì)master節(jié)點(diǎn)集群,,還是需要用戶(hù)自己來(lái)“手工定位鎖”,使鎖的節(jié)點(diǎn)分散到不同的master 集群節(jié)點(diǎn)下。 手工定位鎖,這個(gè)…… 我考慮了下,還是不用 RedLock 吧!如果master節(jié)點(diǎn)變動(dòng)則鎖也存在問(wèn)題,master集群同步等等鎖的同步和鎖失效也是需要考慮的問(wèn)題;
Redisson 的開(kāi)發(fā)者認(rèn)為 Redis 的紅鎖也存在爭(zhēng)議(前文介紹的那個(gè)爭(zhēng)議),但是為了保證可用性,RLock 對(duì)象執(zhí)行的每個(gè) Redis 命令執(zhí)行都通過(guò) Redis 3.0 中引入的 WAIT 命令進(jìn)行同步。

Redisson 的開(kāi)發(fā)者認(rèn)為 Redis 的紅鎖也存在爭(zhēng)議(前文介紹的那個(gè)爭(zhēng)議),但是為了保證可用性,RLock 對(duì)象執(zhí)行的每個(gè)
Redis 命令執(zhí)行都通過(guò) Redis 3.0 中引入的 WAIT 命令進(jìn)行同步。

在這里插入圖片描述

源碼在這一部分。

在這里插入圖片描述

看源碼,同時(shí)發(fā)送了一個(gè) WAIT 1 1000 到 Redis。

結(jié)論:Redisson RedLock 是基于聯(lián)鎖 MultiLock 實(shí)現(xiàn)的,但是使用過(guò)程中需要自己判斷 key 落在哪個(gè)節(jié)點(diǎn)上,對(duì)使用者不是很友好。

紅鎖使用說(shuō)明-官網(wǎng)介紹

基于Redis的Redisson紅鎖RedissonRedLock對(duì)象實(shí)現(xiàn)了Redlock介紹的加鎖算法。該對(duì)象也可以用來(lái)將多個(gè)RLock對(duì)象關(guān)聯(lián)為一個(gè)紅鎖,每個(gè)RLock對(duì)象實(shí)例可以來(lái)自于不同的Redisson實(shí)例。

RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");

RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
// 同時(shí)加鎖:lock1 lock2 lock3
// 紅鎖在大部分節(jié)點(diǎn)上加鎖成功就算成功。
lock.lock();
...
lock.unlock();

大家都知道,如果負(fù)責(zé)儲(chǔ)存某些分布式鎖的某些Redis節(jié)點(diǎn)宕機(jī)以后,而且這些鎖正好處于鎖住的狀態(tài)時(shí),這些鎖會(huì)出現(xiàn)鎖死的狀態(tài)。為了避免這種情況的發(fā)生,Redisson內(nèi)部提供了一個(gè)監(jiān)控鎖的看門(mén)狗,它的作用是在Redisson實(shí)例被關(guān)閉前,不斷的延長(zhǎng)鎖的有效期。默認(rèn)情況下,看門(mén)狗的檢查鎖的超時(shí)時(shí)間是30秒鐘,也可以通過(guò)修改Config.lockWatchdogTimeout來(lái)另行指定。

另外Redisson還通過(guò)加鎖的方法提供了leaseTime的參數(shù)來(lái)指定加鎖的時(shí)間。超過(guò)這個(gè)時(shí)間后鎖便自動(dòng)解開(kāi)了。

RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
// 給lock1,lock2,lock3加鎖,如果沒(méi)有手動(dòng)解開(kāi)的話(huà),10秒鐘后將會(huì)自動(dòng)解開(kāi)
lock.lock(10, TimeUnit.SECONDS);

// 為加鎖等待100秒時(shí)間,并在加鎖成功10秒鐘后自動(dòng)解開(kāi)
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
...
lock.unlock();

紅鎖實(shí)戰(zhàn)

1.注冊(cè)紅鎖的RedissonClient

@Component
public class RedisConfig {
	@Bean(name = "redissonRed1")
    @Primary
    public RedissonClient redissonRed1(){
        Config config = new Config();
        config.useSingleServer().setAddress("127.0.0.1:6379").setDatabase(0);
        return Redisson.create(config);
    }
    @Bean(name = "redissonRed2")
    public RedissonClient redissonRed2(){
        Config config = new Config();
        config.useSingleServer().setAddress("127.0.0.1:6380").setDatabase(0);
        return Redisson.create(config);
    }
    @Bean(name = "redissonRed3")
    public RedissonClient redissonRed3(){
        Config config = new Config();
        config.useSingleServer().setAddress("127.0.0.1:6381").setDatabase(0);
        return Redisson.create(config);
    }
    @Bean(name = "redissonRed4")
    public RedissonClient redissonRed4(){
        Config config = new Config();
        config.useSingleServer().setAddress("127.0.0.1:6382").setDatabase(0);
        return Redisson.create(config);
    }
    @Bean(name = "redissonRed5")
    public RedissonClient redissonRed5(){
        Config config = new Config();
        config.useSingleServer().setAddress("127.0.0.1:6383").setDatabase(0);
        return Redisson.create(config);
    }
  }

配置方式2

基于 Redis 的 Redisson 分布式聯(lián)鎖 RedissonMultiLock 對(duì)象可以將多個(gè) RLock 對(duì)象關(guān)聯(lián)為一個(gè)聯(lián)鎖,每個(gè) RLock 對(duì)象實(shí)例可以來(lái)自于不同的 Redisson 實(shí)例

在這里插入圖片描述

按照官方文檔的說(shuō)法,這里 Redisson 客戶(hù)端可以不是同一個(gè)。當(dāng)然,一般工作中也不會(huì)說(shuō)不用一個(gè)客戶(hù)端吧,可以看出 遍歷所有的鎖,依次加鎖。加鎖邏輯就和可重入鎖加鎖并無(wú)區(qū)別了。所以 Lua 腳本就不進(jìn)行分析了

2. 紅鎖使用

package com.online.taxi.order.service.impl;

import com.online.taxi.order.constant.RedisKeyConstant;
import com.online.taxi.order.service.GrabService;
import com.online.taxi.order.service.OrderService;

import org.redisson.Redisson;
import org.redisson.RedissonRedLock;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;


@Service
public class GrabRedisRedissonRedLockLockServiceImpl implements GrabService {

    // 紅鎖
    @Autowired
    @Qualifier("redissonRed1")
    private RedissonClient redissonRed1;
    @Autowired
    @Qualifier("redissonRed2")
    private RedissonClient redissonRed2;
    @Autowired
    @Qualifier("redissonRed3")
    private RedissonClient redissonRed3;
    @Autowired
    @Qualifier("redissonRed4")
    private RedissonClient redissonRed4;
    @Autowired
    @Qualifier("redissonRed5")
    private RedissonClient redissonRed5;


    @Autowired
	OrderService orderService;

    @Override
    public String grabOrder(int orderId , int driverId){
        System.out.println("紅鎖實(shí)現(xiàn)類(lèi)");
        //生成key
        String lockKey = ("" + orderId).intern();


        //redisson鎖 單節(jié)點(diǎn)
//        RLock rLock = redissonRed1.getLock(lockKey);

        //紅鎖 redis son
        RLock rLock1 = redissonRed1.getLock(lockKey);
        RLock rLock2 = redissonRed2.getLock(lockKey);
        RLock rLock3 = redissonRed3.getLock(lockKey);
        RLock rLock4 = redissonRed4.getLock(lockKey);
        RLock rLock5 = redissonRed5.getLock(lockKey);
        RedissonRedLock rLock = new RedissonRedLock(rLock1,rLock2,rLock3,rLock4,rLock5);



        try {

             /**紅鎖
		     * waitTimeout 嘗試獲取鎖的最大等待時(shí)間,超過(guò)這個(gè)值,則認(rèn)為獲取鎖失敗
		     * leaseTime   鎖的持有時(shí)間,超過(guò)這個(gè)時(shí)間鎖會(huì)自動(dòng)失效(值應(yīng)設(shè)置為大于業(yè)務(wù)處理的時(shí)間,確保在鎖有效期內(nèi)業(yè)務(wù)能處理完)
		     */
            boolean b1 = rLock.tryLock((long)waitTimeout, (long)leaseTime, TimeUnit.SECONDS);

            if (b1){
                System.out.println("加鎖成功");
                // 此代碼默認(rèn) 設(shè)置key 超時(shí)時(shí)間30秒,過(guò)10秒,再延時(shí)
                System.out.println("司機(jī):"+driverId+" 執(zhí)行搶單邏輯");
               
                boolean b = orderService.grab(orderId, driverId);
                if(b) {
                    System.out.println("司機(jī):"+driverId+" 搶單成功");
                }else {
                    System.out.println("司機(jī):"+driverId+" 搶單失敗");
                }
                System.out.println("加鎖成功");
            }else {
                System.out.println("加鎖失敗");
            }


        } finally {
        	rLock.unlock();
        }
        return null;
    }

}

四、單機(jī)版redission 使用

 <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.18.0</version>
        </dependency>

1.配置

    @Value("${spring.redis.host}")
    private String url;

    @Value("${spring.redis.port}")
    private Integer port;

    @Value("${spring.redis.password}")
    private String password;

    @Bean
    public RedissonClient redissonClient(){
        // 配置
        Config config = new Config();
        log.info("Redisson 初始化 {}",String.format("redis://%s:%d",url,port));
        config.useSingleServer().setAddress(String.format("redis://%s:%d",url,port) )
                .setPassword(password);
        // 創(chuàng)建RedissonClient對(duì)象
        return Redisson.create(config);
    }

2. 注入分布式鎖

此處枷鎖后在釋放鎖是解決了鎖的讀寫(xiě)機(jī)制問(wèn)題

@Autowired
private RedissonClient redissonClient;


 public List<? extends Object> getCachedConfigList(String ode) {
        List<StructureVo> configuration =null;
        String key = getCacheKey(orgCode, STR_CONFIG_LIST);
        List<Object> cacheConfig = redisCache.getCacheList(key);
        if (!CollectionUtils.isEmpty(cacheConfig)) {
            return cacheConfig;
        }
        RLock lock = redissonClient.getLock(getReddisonEbomCacheKey());
        try {
            lock.lock(DEFAULT_EXPIRE_SECOND,TimeUnit.SECONDS);
            List<Object> secondCacheConfig = redisCache.getCacheList(key);
            if (!CollectionUtils.isEmpty(secondCacheConfig)) {
                log.info("second lock reddison 查詢(xún)到緩存釋放鎖!");
                reddisnUnlock(getReddisonEbomCacheKey());
                return cacheConfig;
            }
            log.info("reddison枷鎖成功!存放緩存資源!");
            configuration = this.queryAllConfiguration();
            redisCache.setCacheList(key, configuration);
            redisCache.expire(key, DEFAULT_EXPIRE_HOURS, TimeUnit.HOURS);
        } catch (Exception e) {
            log.error("Happen Exception: " + e.getMessage(),e);
        }finally {
            reddisnUnlock(getReddisonEbomCacheKey());
        }
        return configuration;
    }

釋放鎖方法

    private void reddisnUnlock(String key) {
        log.info(" reddison key {}鎖釋放!",key);
        try {
            RLock unlock = redissonClient.getLock(key);
            if (unlock != null && unlock.isHeldByCurrentThread()) {
                unlock.unlock();
            }
        } catch (IllegalMonitorStateException e) {
            log.info("reddison鎖釋放 Exception: " + e.getMessage(),e);
        }
    }

Redis 單實(shí)例版本鎖 NX

單實(shí)例加鎖

SET resource_name my_random_value NX PX 30000

對(duì)于單實(shí)例 Redis 只需要使用這個(gè)命令即可。

  • NX:僅在不存在 key 的時(shí)候才能被執(zhí)行成功;
  • PX:失效時(shí)間,傳入 30000,就是 30s 后自動(dòng)釋放鎖;
  • my_random_value:就是隨機(jī)值,可以是線(xiàn)程號(hào)之類(lèi)的。主要是為了更安全的釋放鎖,釋放鎖的時(shí)候使用腳本告訴 Redis: 只有 key 存在并且存儲(chǔ)的值和我指定的值一樣才能刪除成功。

簡(jiǎn)單描述即為

  • 指定一個(gè) key 作為鎖標(biāo)記,存入 Redis 中,指定一個(gè) 唯一的用戶(hù)標(biāo)識(shí)作為 value。
  • 當(dāng) key 不存在時(shí)才能設(shè)置值,確保同一時(shí)間只有一個(gè)客戶(hù)端進(jìn)程獲得鎖,滿(mǎn)足互斥性特性。
  • 設(shè)置一個(gè)過(guò)期時(shí)間,防止因系統(tǒng)異常導(dǎo)致沒(méi)能刪除這個(gè) key,滿(mǎn)足防死鎖特性。
  • 當(dāng)處理完業(yè)務(wù)之后需要清除這個(gè) key 來(lái)釋放鎖,清除 key 時(shí)需要校驗(yàn) value 值,需要滿(mǎn)足只有加鎖的人才能釋放鎖

可以通過(guò)以下 Lua 腳本實(shí)現(xiàn)鎖釋放:

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

為什么要設(shè)置隨機(jī)值?

主要是為了防止鎖被其他客戶(hù)端刪除。有這么一種情況:

  • 客戶(hù)端 A 獲得了鎖,還沒(méi)有執(zhí)行結(jié)束,但是鎖超時(shí)自動(dòng)釋放了;
  • 客戶(hù)端 B 此時(shí)過(guò)來(lái),是可以獲得鎖的,加鎖成功;
  • 此時(shí),客戶(hù)端 A 執(zhí)行結(jié)束了,要去釋放鎖,如果不對(duì)比隨機(jī)值,就會(huì)把客戶(hù)端 B 的鎖給釋放了。
    當(dāng)然前面看過(guò) Redisson 的處理,這個(gè) my_random_value 存放的是 UUID:ThreadId 組合成的一個(gè)類(lèi)似 931573de-903e-42fd-baa7-428ebb7eda80:1 的字符串。

為什么要用lua腳本操作redis數(shù)據(jù)庫(kù)?

1.減少開(kāi)銷(xiāo)–減少向redis服務(wù)器的請(qǐng)求次數(shù)
2.原子操作–redis將lua腳本作為一個(gè)原子執(zhí)行
3.可復(fù)用–其他客戶(hù)端可以使用已經(jīng)執(zhí)行過(guò)的lua腳本
4.增加redis靈活性–lua腳本可以幫助redis做更多的事情

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

相關(guān)文章

  • YII2框架手動(dòng)安裝Redis擴(kuò)展的過(guò)程

    YII2框架手動(dòng)安裝Redis擴(kuò)展的過(guò)程

    這篇文章主要介紹了YII2框架手動(dòng)安裝Redis擴(kuò)展的過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • Redis為什么快如何實(shí)現(xiàn)高可用及持久化

    Redis為什么快如何實(shí)現(xiàn)高可用及持久化

    這篇文章主要介紹了Redis為什么快如何實(shí)現(xiàn)高可用及持久化,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • Redis數(shù)據(jù)結(jié)構(gòu)類(lèi)型示例解析

    Redis數(shù)據(jù)結(jié)構(gòu)類(lèi)型示例解析

    這篇文章主要為大家介紹了Redis數(shù)據(jù)結(jié)構(gòu)類(lèi)型示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • Redis?Lua同步鎖實(shí)現(xiàn)源碼解析

    Redis?Lua同步鎖實(shí)現(xiàn)源碼解析

    這篇文章主要為大家介紹了Redis?Lua同步鎖實(shí)現(xiàn)源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • Redis?數(shù)據(jù)恢復(fù)及持久化策略分析

    Redis?數(shù)據(jù)恢復(fù)及持久化策略分析

    本文將詳細(xì)分析Redis的數(shù)據(jù)恢復(fù)機(jī)制,持久化策略及其特點(diǎn),并討論選擇持久化策略時(shí)需要考慮的因素,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • Redis調(diào)用Lua腳本及使用場(chǎng)景快速掌握

    Redis調(diào)用Lua腳本及使用場(chǎng)景快速掌握

    Redis?是一種非常流行的內(nèi)存數(shù)據(jù)庫(kù),常用于數(shù)據(jù)緩存與高頻數(shù)據(jù)存儲(chǔ)。大多數(shù)開(kāi)發(fā)人員可能聽(tīng)說(shuō)過(guò)redis可以運(yùn)行?Lua?腳本,但是可能不知道redis在什么情況下需要使用到Lua腳本
    2022-03-03
  • 無(wú)法連接redis服務(wù)器問(wèn)題的解決辦法(非常詳細(xì)!)

    無(wú)法連接redis服務(wù)器問(wèn)題的解決辦法(非常詳細(xì)!)

    這篇文章主要介紹了如何解決Spring?Boot項(xiàng)目連接Redis失敗的問(wèn)題,通過(guò)修改Redis配置文件、添加防火墻白名單或關(guān)閉防火墻,并使用RESP工具進(jìn)行測(cè)試,需要的朋友可以參考下
    2025-02-02
  • redis的hash類(lèi)型操作方法

    redis的hash類(lèi)型操作方法

    Hash 是一個(gè) String 類(lèi)型的 field(字段) 和 value(值) 的映射表,hash 特別適合用于存儲(chǔ)對(duì)象,這篇文章主要介紹了redis的hash類(lèi)型的詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • Redis數(shù)據(jù)類(lèi)型超詳細(xì)講解分析

    Redis數(shù)據(jù)類(lèi)型超詳細(xì)講解分析

    Redis是一個(gè)開(kāi)源的內(nèi)存數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)系統(tǒng),可以用作數(shù)據(jù)庫(kù)、緩存和消息中間件,本文詳細(xì)介紹了Redis的各個(gè)數(shù)據(jù)類(lèi)型、內(nèi)部編碼以及一些高級(jí)功能,如Geo、HyperLogLog和Stream,需要的朋友可以參考下
    2024-12-12
  • 利用Redis實(shí)現(xiàn)SQL伸縮的方法簡(jiǎn)介

    利用Redis實(shí)現(xiàn)SQL伸縮的方法簡(jiǎn)介

    這篇文章主要介紹了利用Redis實(shí)現(xiàn)SQL伸縮的方法,包括講到了鎖和時(shí)間序列等方面來(lái)提升傳統(tǒng)數(shù)據(jù)庫(kù)的性能,需要的朋友可以參考下
    2015-06-06

最新評(píng)論