最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring?Boot?集成Redisson實現(xiàn)分布式鎖詳細(xì)案例

 更新時間:2022年08月05日 08:17:42   作者:劍圣無痕???????  
這篇文章主要介紹了Spring?Boot?集成Redisson實現(xiàn)分布式鎖詳細(xì)案例,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下

前言

Spring Boot集成Redis實現(xiàn)單機分布式鎖針對單機分布式鎖還是存在鎖定續(xù)期、可重入的問題,本文將采用Spring Boot 集成Ression實現(xiàn)分布式鎖進行詳細(xì)講解。

分布式鎖實現(xiàn)

引入jar包

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
      <exclusion>
         <groupId>io.lettuce</groupId>
         <artifactId>lettuce-core</artifactId>
      </exclusion>  
    </exclusions>
   </dependency>
	  
      <dependency>
         <groupId>org.redisson</groupId>
         <artifactId>redisson-spring-boot-starter</artifactId>
         <version>3.13.6</version>
     </dependency>

說明:關(guān)于集成Redisson,我們需要注意與Spring Boot的版本對應(yīng)。

具體對應(yīng)的關(guān)系如下:

注意:3.13.6對應(yīng)的Spring Boot的版本為2.3.0,而redis-spring-data為redis-spring-data-23。我們可以通過查看pom文件的引用從而得到依賴關(guān)系。

Redisson的配置

application.yml中引入redisson.yml配置

  redis:
    redisson:
      file: classpath:redisson.yml

redisson.yml配置

singleServerConfig:
  password: xxxx
  address: "redis://127.0.0.1:6379"
  database: 1
threads: 0
nettyThreads: 0
codec: !<org.redisson.codec.FstCodec> {}
transportMode: "NIO"

說明:本文配置的是單機環(huán)境,如果需要配置集群環(huán)境,可以采用如下配置:

 clusterServersConfig:
          idleConnectionTimeout: 10000
          connectTimeout: 10000
          timeout: 3000
          retryAttempts: 3
          retryInterval: 1500
          failedSlaveReconnectionInterval: 3000
          failedSlaveCheckInterval: 60000
          password: null
          subscriptionsPerConnection: 5
          clientName: null
          loadBalancer: !<org.redisson.connection.balancer.RoundRobinLoadBalancer> {}
          subscriptionConnectionMinimumIdleSize: 1
          subscriptionConnectionPoolSize: 50
          slaveConnectionMinimumIdleSize: 24
          slaveConnectionPoolSize: 64
          masterConnectionMinimumIdleSize: 24
          masterConnectionPoolSize: 64
          readMode: "SLAVE"
          subscriptionMode: "SLAVE"
          nodeAddresses:
          - "redis://127.0.0.1:7004"
          - "redis://127.0.0.1:7001"
          - "redis://127.0.0.1:7000"
          scanInterval: 1000
          pingConnectionInterval: 0
          keepAlive: false
          tcpNoDelay: false
        threads: 16
        nettyThreads: 32
        codec: !<org.redisson.codec.MarshallingCodec> {}
        transportMode: "NIO"

封裝Redisson工具類

@Component
public class RedissonLockUtil
{
    private static final Logger logger = LoggerFactory.getLogger(RedissonLockUtil.class);
    
        @Autowired
        private RedissonClient redissonClient;
     
        /**
         * 加鎖
         * @param lockKey
         * @return
         */
        public RLock lock(String lockKey) 
        {
            RLock lock = redissonClient.getLock(lockKey);
            return lock;
        }
     
        /**
         * 公平鎖
         * @param key
         * @return
         */
        public RLock fairLock(String key) 
        {
            return redissonClient.getFairLock(key);
        }
        
        /**
         * 帶超時的鎖
         * @param lockKey
         * @param timeout 超時時間 單位:秒
         */
        public RLock lock(String lockKey, int timeout) 
        {
            RLock lock = redissonClient.getLock(lockKey);
            lock.lock(timeout, TimeUnit.SECONDS);
            return lock;
        }

        /**
         * 讀寫鎖
         * @param key
         * @return
         */
        public RReadWriteLock readWriteLock(String key) {
            return redissonClient.getReadWriteLock(key);
        }

        /**
         * 帶超時的鎖
         * @param lockKey
         * @param unit 時間單位
         * @param timeout 超時時間
         */
        public RLock lock(String lockKey, TimeUnit unit ,int timeout) {
            RLock lock = redissonClient.getLock(lockKey);
            lock.lock(timeout, unit);
            return lock;
        }

        /**
         * 加鎖
         * @param key
         * @param supplier
         * @return
         */
        public <T> T lock(String key, Supplier<T> supplier) {
            RLock lock = lock(key);
            try {
                lock.lock();
                return supplier.get();
            } finally {
                if (lock != null && lock.isLocked()) {
                    lock.unlock();
                }
            }
        }


        /**
         * 嘗試獲取鎖
         * @param lockKey
         * @param waitTime 等待時間
         * @param leaseTime 自動釋放鎖時間
         * @return
         */
        public  boolean tryLock(String lockKey, int waitTime, int leaseTime) {
            RLock lock = redissonClient.getLock(lockKey);
            try {
                return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                return false;
            }
        }

        /**
         * 嘗試獲取鎖
         * @param lockKey
         * @param unit 時間單位
         * @param waitTime 等待時間
         * @param leaseTime 自動釋放鎖時間
         * @return
         */
        public boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime) {
            RLock lock = redissonClient.getLock(lockKey);
            try {
                return lock.tryLock(waitTime, leaseTime, unit);
            } catch (InterruptedException e) {
                return false;
            }
        }

        /**
         * 釋放鎖
         * @param lockKey
         */
        public void unlock(String lockKey) {
            RLock lock = redissonClient.getLock(lockKey);
            lock.unlock();
        }


        /**
         * 釋放鎖
         * @param lock
         */
        public void unlock(RLock lock) 
        {
            lock.unlock();
        }
    }  

模擬秒殺扣減庫存

 public int lockStock()
    {
        String lockKey="lock:stock";
        String clientId = UUID.randomUUID().toString();

        //加鎖
        RLock lock=redissonLockUtil.lock(lockKey);
        lock.lock();

        try
        {
           logger.info("加鎖成功 clientId:{}",clientId);
           int stockNum= Integer.valueOf((String)redisUtil.get("seckill:goods:stock"));
           if(stockNum>0)
           {
              stockNum--;
              redisUtil.set("seckill:goods:stock",String.valueOf(stockNum));
              logger.info("秒殺成功,剩余庫存:{}",stockNum);
           }
           else
           {
              logger.error("秒殺失敗,剩余庫存:{}", stockNum);
           }
           //獲取庫存數(shù)量
           return stockNum;
        }
        catch (Exception e)
        {
           logger.error("decry stock eror",e);
        }
        finally
        {
            if(lock!=null)
            {
                lock.unlock(); 
            }
        }
        return 0;
    }

測試代碼

@RequestMapping("/redisLockTest")
    public void redisLockTest()
    {
        // 初始化秒殺庫存數(shù)量
        redisUtil.set("seckill:goods:stock", "10");

        List<Future> futureList = new ArrayList<>();

        //多線程異步執(zhí)行
        ExecutorService executors = Executors.newScheduledThreadPool(10);
        //
        for (int i = 0; i < 30; i++)
        {
            futureList.add(executors.submit(this::lockStock));

            try
            {
               Thread.sleep(100);
            }
            catch (InterruptedException e) 
            {
               logger.error("redisLockTest error",e);
            }
        }

        // 等待結(jié)果,防止主線程退出
        futureList.forEach(t -> {
            try 
            {
                int stockNum =(int) t.get();
                logger.info("庫存剩余數(shù)量:{}",stockNum);
            }
            catch (Exception e)
            {
               logger.error("get stock num error",e);
            }
        });
    }

執(zhí)行結(jié)果如下:

總結(jié)

本文針對Spring Boot集成Redisson的基本使用,關(guān)于Redisson源碼的分析將在后續(xù)的文章中進行講解,如有疑問,請隨時反饋,

相關(guān)文章

  • 淺談Java HttpURLConnection請求方式

    淺談Java HttpURLConnection請求方式

    這篇文章主要介紹了淺談Java HttpURLConnection請求方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • idea啟動多個SpringBoot服務(wù)實例的最優(yōu)解決方法

    idea啟動多個SpringBoot服務(wù)實例的最優(yōu)解決方法

    啟動SpringBoot項目其實就是啟動Tomcat等服務(wù)容器,只要這個端口不同就能啟動多個服務(wù)實例了,本文主要介紹了idea啟動多個SpringBoot服務(wù)實例的最優(yōu)解決方法,感興趣的可以了解一下
    2024-05-05
  • SpringBoot?實現(xiàn)CAS?Server統(tǒng)一登錄認(rèn)證的詳細(xì)步驟

    SpringBoot?實現(xiàn)CAS?Server統(tǒng)一登錄認(rèn)證的詳細(xì)步驟

    ??CAS(Central?Authentication?Service)中心授權(quán)服務(wù),是一個開源項目,目的在于為Web應(yīng)用系統(tǒng)提供一種可靠的單點登錄,這篇文章主要介紹了SpringBoot?實現(xiàn)CAS?Server統(tǒng)一登錄認(rèn)證,需要的朋友可以參考下
    2024-02-02
  • 基于springboot攔截器HandlerInterceptor的注入問題

    基于springboot攔截器HandlerInterceptor的注入問題

    這篇文章主要介紹了springboot攔截器HandlerInterceptor的注入問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • idea使用Vim的技巧大全分享

    idea使用Vim的技巧大全分享

    vim是一個高度可配置的文本編輯器,非常穩(wěn)定,可以高效的創(chuàng)建任何文本、持久的、多級撤銷樹、支持?jǐn)?shù)百種變成語言和格式、與許多工具集成,本文給大家分享了idea使用Vim的技巧大全,需要的朋友可以參考下
    2024-05-05
  • java加載屬性配置properties文件的方法

    java加載屬性配置properties文件的方法

    這篇文章主要介紹了java加載屬性配置properties文件的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • Springboot如何優(yōu)雅地進行字段校驗

    Springboot如何優(yōu)雅地進行字段校驗

    這篇文章主要給大家介紹了關(guān)于Springboot如何優(yōu)雅地進行字段校驗的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • myeclipse無法部署項目問題及解決方法

    myeclipse無法部署項目問題及解決方法

    最近小編遇到到棘手的問題,myeclipse無法部署項目,點擊這個部署按鈕沒有反應(yīng)。怎么解決呢,下面小編給大家代理的myeclipse無法部署項目問題及解決方法 ,感興趣的朋友一起看看吧
    2018-10-10
  • 詳解SpringBoot啟動項目后執(zhí)行方法的幾種方式

    詳解SpringBoot啟動項目后執(zhí)行方法的幾種方式

    在項目開發(fā)中某些場景必須要用到啟動項目后立即執(zhí)行方式的功能,本文主要聊聊實現(xiàn)立即執(zhí)行的幾種方法,具有一定的參考價值,感興趣的可以了解一下
    2023-09-09
  • java中break和continue源碼解析

    java中break和continue源碼解析

    這篇文章主要針對java中break和continue的區(qū)別進行詳細(xì)介紹,幫助大家更好的學(xué)習(xí)了解java中break和continue源碼,感興趣的小伙伴們可以參考一下
    2016-06-06

最新評論

延庆县| 隆昌县| 大丰市| 北流市| 阳朔县| 广州市| 临湘市| 衡山县| 西昌市| 苍山县| 无锡市| 新民市| 宜君县| 婺源县| 仙居县| 裕民县| 泸溪县| 黄浦区| 涞水县| 中江县| 阳泉市| 汝城县| 军事| 双桥区| 桐城市| 丰宁| 桂东县| 尼勒克县| 阳山县| 怀安县| 保靖县| 会宁县| 遂川县| 龙州县| 于田县| 绍兴县| 儋州市| 城固县| 敖汉旗| 永泰县| 开封市|