日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

这样实现分布式锁,才叫优雅!

發布時間:2025/3/15 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 这样实现分布式锁,才叫优雅! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

概述

提到分布式鎖大家都會想到如下兩種:

  • 基于Redisson組件,使用redlock算法實現

  • 基于Apache Curator,利用Zookeeper的臨時順序節點模型實現

今天我們來說說第三種,使用?Spring Integration?實現。

Spring Integration在基于Spring的應用程序中實現輕量級消息傳遞,并支持通過聲明適配器與外部系統集成。Spring Integration的主要目標是提供一個簡單的模型來構建企業集成解決方案,同時保持關注點的分離,這對于生成可維護,可測試的代碼至關重要。我們熟知的 Spring Cloud Stream的底層就是Spring Integration。

官方地址:https://github.com/spring-projects/spring-integration

Spring Integration提供的全局鎖目前為如下存儲提供了實現:

  • Gemfire

  • JDBC

  • Redis

  • Zookeeper

它們使用相同的API抽象,這意味著,不論使用哪種存儲,你的編碼體驗是一樣的。試想一下你目前是基于zookeeper實現的分布式鎖,哪天你想換成redis的實現,我們只需要修改相關依賴和配置就可以了,無需修改代碼。下面是你使用?Spring Integration?實現分布式鎖時需要關注的方法:

方法名描述
lock()Acquires the lock.?加鎖,如果已經被其他線程鎖住或者當前線程不能獲取鎖則阻塞
lockInterruptibly()Acquires the lock unless the current thread is interrupted.?加鎖,除非當前線程被打斷。
tryLock()Acquires the lock only if it is free at the time of invocation.?嘗試加鎖,如果已經有其他鎖鎖住,獲取當前線程不能加鎖,則返回false,加鎖失敗;加鎖成功則返回true
tryLock(long time, TimeUnit unit)Acquires the lock if it is free within the given waiting time and the current thread has not been interrupted.?嘗試在指定時間內加鎖,如果已經有其他鎖鎖住,獲取當前線程不能加鎖,則返回false,加鎖失敗;加鎖成功則返回true
unlock()Releases the lock.?解鎖

實戰

話不多說,我們看看使用?Spring Integration?如何基于redis和zookeeper快速實現分布式鎖,至于Gemfire 和 Jdbc的實現大家自行實踐。

基于Redis實現

  • 引入相關組件

<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><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
  • 在application.yml中添加redis的配置

spring:redis:host:?172.31.0.149port:?7111
  • 建立配置類,注入RedisLockRegistry

@Configuration public?class?RedisLockConfiguration?{@Beanpublic?RedisLockRegistry?redisLockRegistry(RedisConnectionFactory?redisConnectionFactory){return?new?RedisLockRegistry(redisConnectionFactory,?"redis-lock");}}
  • 編寫測試代碼

@RestController @RequestMapping("lock") @Log4j2 public?class?DistributedLockController?{@Autowiredprivate?RedisLockRegistry?redisLockRegistry;@GetMapping("/redis")public?void?test1()?{Lock?lock?=?redisLockRegistry.obtain("redis");try{//嘗試在指定時間內加鎖,如果已經有其他鎖鎖住,獲取當前線程不能加鎖,則返回false,加鎖失敗;加鎖成功則返回trueif(lock.tryLock(3,?TimeUnit.SECONDS)){log.info("lock?is?ready");TimeUnit.SECONDS.sleep(5);}}?catch?(InterruptedException?e)?{log.error("obtain?lock?error",e);}?finally?{lock.unlock();}} }
  • 測試
    啟動多個實例,分別訪問/lock/redis?端點,一個正常秩序業務邏輯,另外一個實例訪問出現如下錯誤說明第二個實例沒有拿到鎖,證明了分布式鎖的存在。

注意,如果使用新版Springboot進行集成時需要使用Redis4版本,否則會出現下面的異常告警,主要是?unlock()?釋放鎖時使用了UNLINK命令,這個需要Redis4版本才能支持。

2020-05-14?11:30:24,781?WARN??RedisLockRegistry:339?-?The?UNLINK?command?has?failed?(not?supported?on?the?Redis?server?);?falling?back?to?the?regular?DELETE?command org.springframework.data.redis.RedisSystemException:?Error?in?execution;?nested?exception?is?io.lettuce.core.RedisCommandExecutionException:?ERR?unknown?command?'UNLINK'

基于Zookeeper實現

  • 引入組件

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-integration</artifactId> </dependency><dependency><groupId>org.springframework.integration</groupId><artifactId>spring-integration-zookeeper</artifactId> </dependency>
  • 在application.yml中添加zookeeper的配置

zookeeper:??host:?172.31.0.43:2181
  • 建立配置類,注入ZookeeperLockRegistry

@Configuration public?class?ZookeeperLockConfiguration?{@Value("${zookeeper.host}")private?String?zkUrl;@Beanpublic?CuratorFrameworkFactoryBean?curatorFrameworkFactoryBean(){return?new?CuratorFrameworkFactoryBean(zkUrl);}@Beanpublic?ZookeeperLockRegistry?zookeeperLockRegistry(CuratorFramework?curatorFramework){return?new?ZookeeperLockRegistry(curatorFramework,"/zookeeper-lock");} }
  • 編寫測試代碼

@RestController @RequestMapping("lock") @Log4j2 public?class?DistributedLockController?{@Autowiredprivate?ZookeeperLockRegistry?zookeeperLockRegistry;@GetMapping("/zookeeper")public?void?test2()?{Lock?lock?=?zookeeperLockRegistry.obtain("zookeeper");try{//嘗試在指定時間內加鎖,如果已經有其他鎖鎖住,獲取當前線程不能加鎖,則返回false,加鎖失敗;加鎖成功則返回trueif(lock.tryLock(3,?TimeUnit.SECONDS)){log.info("lock?is?ready");TimeUnit.SECONDS.sleep(5);}}?catch?(InterruptedException?e)?{log.error("obtain?lock?error",e);}?finally?{lock.unlock();}} }
  • 測試
    啟動多個實例,分別訪問/lock/zookeeper?端點,一個正常秩序業務邏輯,另外一個實例訪問出現如下錯誤說明第二個實例沒有拿到鎖,證明了分布式鎖的存在。

往期推薦

6 個 Java 工具,輕松分析定位 JVM 問題!


微軟再出手!這次要干翻 IDEA 了。。


明明還有大量內存,為啥報錯“無法分配內存”?


有道無術,術可成;有術無道,止于術

歡迎大家關注Java之道公眾號

好文章,我在看??

總結

以上是生活随笔為你收集整理的这样实现分布式锁,才叫优雅!的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。