<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          簡潔實(shí)用的Redis分布式鎖用法

          共 3016字,需瀏覽 7分鐘

           ·

          2020-08-03 11:14



          在微服務(wù)中很多情況下需要使用到分布式鎖功能,而目前比較常見的方案是通過Redis來實(shí)現(xiàn)分布式鎖,網(wǎng)上關(guān)于分布式鎖的實(shí)現(xiàn)方式有很多,早期主要是基于Redisson等客戶端,但在Spring Boot2.x以上版本中使用Redis時(shí),其客戶端庫已經(jīng)默認(rèn)使用lettuce。
          所以本文將直接介紹在Spring Boot2.x以上項(xiàng)目中快速使用Redis分布式鎖的功能的方法,希望能夠更新你的知識(shí)庫!




          Redis分布式鎖原理概述



          實(shí)際上Redis服務(wù)本身并不提供分布式鎖這樣的機(jī)制,但是作為全局Key-Value存儲(chǔ)系統(tǒng),客戶端可以利用Redis提供的基本功能并通過一定的算法設(shè)計(jì)來實(shí)現(xiàn)分布式鎖功能。目前已有不少博客文章及代碼庫描述了如何使用Redis來實(shí)現(xiàn)分布式鎖,但是許多實(shí)現(xiàn)相對(duì)比較簡單,安全性也比較低。

          在Redis的官方文檔中推薦了一種叫做RedLock的算法來實(shí)現(xiàn)基于Redis的分布式鎖功能,現(xiàn)階段已存在基于該算法的多種語言版本的Redis客戶端實(shí)現(xiàn)庫。其中Java領(lǐng)域最為知名的是Redisson庫。但由于Redisson不僅實(shí)現(xiàn)了分布式鎖功能,還額外實(shí)現(xiàn)了一套R(shí)edis分布式數(shù)據(jù)結(jié)構(gòu),因此會(huì)顯得比較重,加上最新的基于Spring Boot.2.x以上版本使用Redis時(shí),其客戶端庫已經(jīng)默認(rèn)使用了lettuce(比Redisson、Jedis線程更安全、更輕量級(jí)的一種Java Redis客戶端庫)的封裝,所以為了更加符合微服務(wù)場景下的使用,在實(shí)踐中往往會(huì)選擇基于RedLock算法自行實(shí)現(xiàn)分布式鎖。

          本案例也將演示如何RedLock算法來實(shí)現(xiàn)Redis分布式鎖功能,不過在此之前讓我們先來看看RedLock算法是如何運(yùn)行的,示意圖如下:





          以上就是實(shí)現(xiàn)Redis分布式鎖官方推薦的RedLock算法邏輯,它是一種多節(jié)點(diǎn)Redis的分布式鎖算法,可以有效防止單節(jié)點(diǎn)故障問題。其執(zhí)行步驟說明如下:


          • 首先Redis客戶端獲取當(dāng)前系統(tǒng)時(shí)間,以毫秒為單位;
          • 然后客戶端會(huì)順序地嘗試向Redis集群中的每個(gè)節(jié)點(diǎn)獲取鎖,其具體步驟是使用相同的鍵Key名和隨機(jī)值;在向每個(gè)Redis節(jié)點(diǎn)獲取鎖的過程中,客戶端會(huì)以比鎖過期時(shí)間小得多的時(shí)間來設(shè)定超時(shí)機(jī)制,例如鎖的整個(gè)超時(shí)時(shí)間為10秒,集群有5個(gè)節(jié)點(diǎn),那么每個(gè)節(jié)點(diǎn)獲取鎖的超時(shí)時(shí)間可能會(huì)被限制在5~50毫秒之間,這是為了防止在某個(gè)節(jié)點(diǎn)不可用的情況下,客戶端等待時(shí)間過長,造成性能阻塞;
          • 之后隨著各節(jié)點(diǎn)獲取鎖結(jié)果的反饋,Redis客戶端會(huì)對(duì)獲取情況進(jìn)行判斷,如果獲取各節(jié)點(diǎn)鎖的總時(shí)間小于鎖的超時(shí)時(shí)間設(shè)置,并且成功獲取鎖的節(jié)點(diǎn)數(shù)目大于N/2+1個(gè)(例如5個(gè)節(jié)點(diǎn)至少要有3個(gè)節(jié)點(diǎn)成功獲取鎖),滿足上述條件的情況下,Redis客戶端才會(huì)認(rèn)為獲取鎖成功,否則就會(huì)認(rèn)為鎖獲取失敗,并依次釋放掉各個(gè)節(jié)點(diǎn)的鎖信息;
          • 獲取鎖成功后即可以安全地執(zhí)行操作,完成后再依次釋放各節(jié)點(diǎn)鎖持有的鎖信息;


          ?
          實(shí)現(xiàn)上述算法的Redis客戶端可以基本上保證分布式鎖的有效性及安全性的幾個(gè)基本特性要求:


          • 互斥:任何時(shí)刻只能有一個(gè)Redis客戶端獲取鎖;
          • 無死鎖:即使鎖定資源的服務(wù)崩潰或者分區(qū),仍然能釋放鎖);
          • 容錯(cuò)性:只要多數(shù)redis節(jié)點(diǎn)(一半以上)在使用,Redis客戶端就可以獲取和釋放鎖;


          Spring Boot集成使用方式



          通過前面內(nèi)容的描述,相信你對(duì)實(shí)現(xiàn)Redis分布式鎖的基本算法應(yīng)該有了一定的認(rèn)識(shí)和理解。而在實(shí)踐的過程中可以依據(jù)該算法自行定制實(shí)現(xiàn),但實(shí)際上Spring早就提供了基于該算法的Redis的分布式鎖的實(shí)現(xiàn)。其具體使用步驟如下:

          1)在工程pom.xml文件中引入Spring Integration依賴,代碼如下:

          <dependency>
          ????<groupId>org.springframework.bootgroupId>
          ????<artifactId>spring-boot-starter-integrationartifactId>
          dependency>

          <dependency>
          ????<groupId>org.springframework.integrationgroupId>
          ????<artifactId>spring-integration-redisartifactId>
          dependency>


          目前Spring所提供的分布式鎖相關(guān)的代碼被遷移在Spring Integration子項(xiàng)目中,所以這里引入其相關(guān)依賴。


          2)編寫RedisLock的配置類,代碼如下:


          @Configuration
          public?class?RedisLockConfiguration?{
          ????@Bean
          ????public?RedisLockRegistry?redisLockRegistry(RedisConnectionFactory?redisConnectionFactory)?{
          ????????return?new?RedisLockRegistry(redisConnectionFactory,?"payment");
          ????}
          }


          以上配置代碼加載的前提在于應(yīng)用已經(jīng)集成了Redis服務(wù)訪問鏈接信息,具體Spring Boot項(xiàng)目集成Redis訪問的方式比較簡單可以參考其他資料。


          3)分布式鎖的具體使用方式,代碼片段如下:


          /**
          ?*?引入Redis分布式鎖依賴組件
          ?*/

          @Autowired
          private?RedisLockRegistry?redisLockRegistry;

          @Override
          public?UnifiedPayBO?unifiedPay(UnifiedPayDTO?unifiedPayDTO)?
          {
          ????...
          ????//創(chuàng)建Redis分布式鎖
          ????Lock?lock?=?redisLockRegistry.obtain(redisLockPrefix?+?unifiedPayDTO.getOrderId());
          ????try?{??????
          ????????//嘗試獲取鎖
          ????????boolean?isLock?=?lock.tryLock(1,?TimeUnit.SECONDS);
          ????????if?(isLock)?{
          ????????????//執(zhí)行業(yè)務(wù)邏輯
          ????????????...
          ????????}
          ????}?catch?(InterruptedException?e)?{
          ????????e.printStackTrace();
          ????}?finally?{
          ????????//釋放分布式鎖
          ????????lock.unlock();
          ????}
          ????...
          }



          上述代碼為訂單防重時(shí)使用Redis分布鎖的示例代碼,通過依賴注入RedisLockRegistry實(shí)例來實(shí)現(xiàn)分布式鎖的相關(guān)操作,例如obtain()方法創(chuàng)建鎖、tryLock()持有鎖及unlock()釋放鎖等。


          —————END—————


          推薦閱讀:

          實(shí)戰(zhàn):一鍵生成前后端代碼,Mybatis-Plus代碼生成器讓我舒服了
          為什么要重寫 hashcode 和 equals 方法?
          SpringBoot @Value 解析集合配置

          ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

          瀏覽 89
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  好想操骚逼无码视频 | 亚洲操逼大全 | 天天干天天爽天天玩 | 91 丝袜一区二区三区 | 欧美一区二区电影在线观看 |