中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring Boot中怎么利用Redis實現分布式鎖

發布時間:2021-08-06 16:05:10 來源:億速云 閱讀:375 作者:Leah 欄目:編程語言

Spring Boot中怎么利用Redis實現分布式鎖,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

分布式鎖介紹

Spring Boot 實現 Redis 分布式鎖在 spring-integration 這個項目中

首先來看下 LockRegistry 鎖注冊接口的所有實現類結構圖:

Spring Boot中怎么利用Redis實現分布式鎖

DefaultLockRegistry 就是純單機的可重入鎖,PassThruLockRegistry 是一個空實現類,也都沒有什么利用價值。

Spring Integration 4.0 引入了基于 Redis 的分布式鎖:RedisLockRegistry,并且從 5.0 開始實現了 ExpirableLockRegistry 接口,用來移除超時且沒有用的鎖。

分布式鎖實戰

添加依賴

上面提到 Spring Boot 實現 Redis 分布式鎖在 spring-integration 這個項目中,所以需要這三個依賴:

  •  spring-boot-starter-data-redis

  •  spring-boot-starter-integration

  •  spring-integration-redis 

<dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-data-redis</artifactId>  </dependency>  <dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-integration</artifactId> </dependency>  <dependency>   <groupId>org.springframework.integration</groupId>   <artifactId>spring-integration-redis</artifactId>  </dependency>

Spring Boot 基礎知識就不介紹了,不熟悉的可以關注公眾號Java技術棧,在后臺回復:boot,可以閱讀我寫的歷史實戰教程。

配置分布式鎖

@Bean(destroyMethod = "destroy")  public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) {      return new RedisLockRegistry(redisConnectionFactory, "lock");  }

使用示例

@GetMapping("/redis/lock")  public String lock(@RequestParam("key") String key) {      for (int i = 0; i < 10; i++) {          new Thread(() -> {              redisLockService.lock(key);              try {                  Thread.sleep(3000L);              } catch (InterruptedException e) {                  e.printStackTrace();              }              System.out.println(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));              redisLockService.unlock(key);          }          ).start();      }      return "OK";  }

RedisLockService 是我封裝了的一個 Redis 鎖服務,代碼有點多,這里就不貼了,完整的代碼示例在 Github 上,大家可以 Star 一下:

https://github.com/javastacks/spring-boot-best-practice

測試:

http://localhost:8080/redis/lock?key=yeah

輸出:

2020-06-23 11:15:34  2020-06-23 11:15:37  2020-06-23 11:15:40  2020-06-23 11:15:43  2020-06-23 11:15:46  2020-06-23 11:15:49  2020-06-23 11:15:52  2020-06-23 11:15:55 2020-06-23 11:15:58  2020-06-23 11:16:01

可以看到每個線程需要等上一個線程休眠 3 秒后才能獲取到鎖。

源碼分析

集成完了,會使用了,還得研究下 RedisLockRegistry 的源碼,不然遇到什么坑還得再踩一篇。

RedisLockRegistry 有兩個類構造器:

Spring Boot中怎么利用Redis實現分布式鎖

  •  connectionFactory:Redis 連接工廠

  •  registryKey:鎖前綴

  •  expireAfter:失效時間(非必須項,默認60秒)

所以,我們要注冊 expireAfter 這個選項,默認 60 秒是否滿足業務需要,如果超過默認的 60 少時間,否則將導致鎖失效。

還有兩個和 RedisLockRegistry  相關且很重要的成員變量:

private final String clientId = UUID.randomUUID().toString();  private final Map<String, RedisLock> locks = new ConcurrentHashMap<>();
  •  clientId:

首先用來標識當前 RedisLockRegistry 實例ID,并且在設置、移除鎖的時候都會要用到,用來判斷是不是當前的鎖注冊實例。

  •  locks:

用來在內存中緩存當前鎖注冊實例所有鎖對象。

獲取鎖對象

如下面獲取鎖對象源碼所示:

Spring Boot中怎么利用Redis實現分布式鎖

每個 key 在內存中(ConcurrentHashMap)都對應一個鎖對象,鎖對象有生成過就直接返回,沒有就生成再返回,有了這個鎖對象才能進行上鎖和解鎖操作。

這個鎖對象(RedisLock)其實也是實現了 Java 中的 java.util.concurrent.locks.Lock 鎖接口:

Spring Boot中怎么利用Redis實現分布式鎖

鎖對象(RedisLock)也有兩個很重要的成員變量:

private final ReentrantLock localLock = new ReentrantLock();  private volatile long lockedAt;
  •  localLock:

localLock 是一個本地內存可重入鎖,每次去 Redis 上鎖前,都要用本地 localLock 上鎖先,這樣能做到盡可能的少往 Redis 上鎖,也能從一方面提升鎖的性能。

  •  lockedAt:

lockedAt 上鎖時間,移除過時鎖會用到。

阻塞上鎖

RedisLock#lock():

Spring Boot中怎么利用Redis實現分布式鎖

每隔 100 毫秒嘗試獲取一次鎖,直到獲取鎖成功為止,不接受打斷異常,遇到其他異常會釋放本地鎖返回異常并結束。

主要看下設置 Redis 鎖的 Lua 腳本:

Spring Boot中怎么利用Redis實現分布式鎖

根據 key 查詢其對應的值:clientId,如果和當前 clientId 一致則延長失效時間,如果 clientId 不存在就直接上鎖,以上都不成立返回 false。

看完上述內容,你們掌握Spring Boot中怎么利用Redis實現分布式鎖的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

资讯| 军事| 资源县| 德令哈市| 类乌齐县| 平远县| 庐江县| 嘉义县| 噶尔县| 肇东市| 松潘县| 奉贤区| 浦北县| 吴旗县| 大城县| 阳春市| 黔江区| 蒙自县| 延吉市| 改则县| 盐亭县| 光山县| 乐平市| 介休市| 赤城县| 永年县| 朝阳县| 定襄县| 易门县| 定安县| 通山县| 兰溪市| 西贡区| 遂溪县| 开化县| 三原县| 杭州市| 广平县| 常宁市| 华亭县| 马鞍山市|