亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot3+Redis實現(xiàn)分布式鎖的配置方法

 更新時間:2024年07月12日 10:33:35   作者:piaoyunlive  
這篇文章主要介紹了SpringBoot3+Redis實現(xiàn)分布式鎖,本文通過實例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧

SpringBoot3+Redis+Lua腳本實現(xiàn)分布式鎖 

相關(guān)依賴包

<spring-boot.version>3.0.2</spring-boot.version>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

application.yml Redis配置

spring:
  data:
    redis:
      host: 192.168.5.133
      port: 6379
      password:
      database: 0
      lettuce:
        pool:
          max-active: 8
          max-idle: 8
          min-idle: 0
          max-wait: "-1ms"

Lua腳本

獲取鎖腳本 tryLock.lua

-- KEYS[1] 是鎖的鍵
-- ARGV[1] 是請求ID
-- ARGV[2] 是鎖的過期時間(秒)
local lockKey = KEYS[1]
local requestId = ARGV[1]
local expireTime = tonumber(ARGV[2])
-- 嘗試獲取鎖
local lockValue = redis.call('GET', lockKey)
-- 如果鎖不存在,嘗試設(shè)置鎖
if not lockValue then
    if redis.call('SETNX', lockKey, requestId) then
        -- 設(shè)置鎖的過期時間
        redis.call('EXPIRE', lockKey, expireTime)
        return 1
    end
    return 0
elseif lockValue == requestId then
    -- 如果請求ID與當(dāng)前鎖持有者匹配,延長鎖的過期時間
    redis.call('EXPIRE', lockKey, expireTime)
    return 1
else
    -- 鎖被其他請求持有,無法獲取鎖
    return 0
end

釋放鎖腳本 releaseLock.lua

-- KEYS[1] 是鎖的鍵
-- ARGV[1] 是請求ID
local lockKey = KEYS[1]
local requestId = ARGV[1]
-- 獲取鎖的值
local lockValue = redis.call('GET', lockKey)
-- 檢查請求ID是否匹配鎖的持有者
if lockValue == requestId then
    -- 刪除鎖
    redis.call('DEL', lockKey)
    return 1
else
    return 0
end

Service層實現(xiàn)

package pub.qingyun.service;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Service;
import java.util.List;
/**
 * @author CQY
 * @version 1.0
 * @date 2024/7/10 10:29
 **/
@Service
@Slf4j
public class RedisLockService {
    private static final String LOCK_KEY = "distributed-lock";
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    private static final DefaultRedisScript<Long> TRY_LOCK_SCRIPT = new DefaultRedisScript<>();
    private static final DefaultRedisScript<Long> RELEASE_LOCK_SCRIPT = new DefaultRedisScript<>();
    static {
        TRY_LOCK_SCRIPT.setScriptSource(new ResourceScriptSource(new ClassPathResource("script/tryLock.lua")));
        TRY_LOCK_SCRIPT.setResultType(Long.class);
        RELEASE_LOCK_SCRIPT.setScriptSource(new ResourceScriptSource(new ClassPathResource("script/releaseLock.lua")));
        RELEASE_LOCK_SCRIPT.setResultType(Long.class);
    }
    /**
     * 嘗試獲取分布式鎖。
     *
     * @param requestId  請求ID,用于唯一標(biāo)識鎖的持有者。
     * @param expireTime 鎖的過期時間(秒)。
     * @return 如果成功獲取鎖返回true,否則返回false。
     */
    public boolean tryLock(String requestId, int expireTime) {
        Object result = stringRedisTemplate.execute(TRY_LOCK_SCRIPT,
                List.of(LOCK_KEY),
                requestId,
                String.valueOf(expireTime));
        assert result != null;
        return Long.parseLong(result.toString()) == 1L;
    }
    /**
     * 釋放分布式鎖。
     *
     * @param requestId 請求ID,必須與獲取鎖時使用的相同。
     * @return 如果鎖成功釋放返回true,否則返回false。
     */
    public boolean releaseLock(String requestId) {
        Object result = stringRedisTemplate.execute(RELEASE_LOCK_SCRIPT,
                List.of(LOCK_KEY),
                requestId);
        assert result != null;
        return Long.parseLong(result.toString()) == 1L;
    }
}

Controller調(diào)用示例代碼

package pub.qingyun.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import pub.qingyun.service.RedisLockService;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
 * @author CQY
 * @version 1.0
 * @date 2024/7/10 10:43
 **/
@Slf4j
@RestController
public class LuaLockController {
    // Lock timeout in seconds
    private static final int LOCK_TIMEOUT_SECONDS = 30000;
    private final RedisLockService lockService;
    @Autowired
    public LuaLockController(RedisLockService lockService) {
        this.lockService = lockService;
    }
    /**
     * 嘗試獲取鎖并執(zhí)行一些操作,然后釋放鎖。
     * 通過嘗試獲取鎖來確保操作的原子性,避免并發(fā)問題
     */
    @GetMapping("/performOperation")
    public String performOperation() {
        // 使用UUID作為請求ID
        String requestId = UUID.randomUUID().toString();
        try {
            // 嘗試獲取鎖
            boolean tryLock = lockService.tryLock(requestId, LOCK_TIMEOUT_SECONDS);
            log.info("獲取鎖[{}][{}]", requestId, tryLock);
            if (tryLock) {
                // 執(zhí)行關(guān)鍵操作
                log.info("開始執(zhí)行主任務(wù)[{}]...", requestId);
                TimeUnit.SECONDS.sleep(5); // 模擬耗時操作
                log.info("任務(wù)[{}]執(zhí)行完成", requestId);
                return requestId + " completed successfully.";
            } else {
                log.info("無法獲取鎖,任務(wù)[{}]被拒絕", requestId);
                return "無法獲取鎖,任務(wù)[" + requestId + "]被拒絕";
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("Interrupted while performing operation.", e);
            return "任務(wù)[" + requestId + "]執(zhí)行失敗";
        } finally {
            // 釋放鎖
            boolean releaseLock = lockService.releaseLock(requestId);
            log.info("釋放鎖[{}][{}]", requestId, releaseLock);
        }
    }
}

SpringBoot3+Redisson實現(xiàn)分布式鎖

添加依賴包

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

配置類

@Configuration
package pub.qingyun.config;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
 * @author CQY
 * @version 1.0
 * @date 2024/7/5 10:58
 **/
@Configuration
public class RedisConfig {
    @Value("${spring.data.redis.host}")
    private String host;
    @Value("${spring.data.redis.port}")
    private String port;
    @Bean
    public RedissonClient redissonClient() {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://" + host + ":" + port + "");
        return Redisson.create(config);
    }
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }
}

實現(xiàn)類

 	@Resource
    private RedissonClient redissonClient;
	public void example() {
        RLock rlock = redissonClient.getLock("myLock");
        try {
            boolean locked = rlock.tryLock(0, 800, TimeUnit.MILLISECONDS);
            if (locked) {
                // TODO
            } else {
                log.warn("Thread[{}]Could not acquire lock.", Thread.currentThread().getName());
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("Error occurred while trying to acquire lock.", e);
        } finally {
            if (rlock.isHeldByCurrentThread()) {
                rlock.unlock();
            }
        }
    }

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

相關(guān)文章

  • 使用Redis實現(xiàn)記錄訪問次數(shù)的三種方案

    使用Redis實現(xiàn)記錄訪問次數(shù)的三種方案

    這篇文章主要介紹了使用Redis實現(xiàn)記錄訪問次數(shù)的三種方案,文中通過代碼示例和圖文講解的非常詳細,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-09-09
  • 詳解Redis緩存預(yù)熱的實現(xiàn)方法

    詳解Redis緩存預(yù)熱的實現(xiàn)方法

    緩存預(yù)熱是一種在程序啟動或緩存失效之后,主動將熱點數(shù)據(jù)加載到緩存中的策略,本文將給大家分享一下如何實現(xiàn)Redis的緩存預(yù)熱,文中有詳細的實現(xiàn)代碼,需要的朋友可以參考下
    2023-10-10
  • 淺談一下Redis的數(shù)據(jù)結(jié)構(gòu)

    淺談一下Redis的數(shù)據(jù)結(jié)構(gòu)

    這篇文章主要介紹了淺談一下Redis的數(shù)據(jù)結(jié)構(gòu),簡單字符串結(jié)構(gòu)被用于存儲redis的key對象和String類型的value對象,其中的free和len字段可以輕松的使得在該字符串被修改時判斷是否需要擴容,需要的朋友可以參考下
    2023-08-08
  • Redis中過期鍵刪除的三種方法

    Redis中過期鍵刪除的三種方法

    Redis中可以設(shè)置鍵的過期時間,并且通過取出過期字典(expires dict)中鍵的過期時間和當(dāng)前時間比較來判斷是否過期,那么一個過期的鍵是怎么被刪除的呢?本文給大家總結(jié)了三種方法,選了其中兩種給大家詳細的介紹一下,需要的朋友可以參考下
    2024-05-05
  • Redis的五種基本類型和業(yè)務(wù)場景和使用方式

    Redis的五種基本類型和業(yè)務(wù)場景和使用方式

    Redis是一種高性能的鍵值存儲數(shù)據(jù)庫,支持多種數(shù)據(jù)結(jié)構(gòu)如字符串、列表、集合、哈希表和有序集合等,它提供豐富的API和持久化功能,適用于緩存、消息隊列、排行榜等多種場景,Redis能夠?qū)崿F(xiàn)高速讀寫操作,尤其適合需要快速響應(yīng)的應(yīng)用
    2024-10-10
  • Redis集群水平擴展、集群中添加以及刪除節(jié)點的操作

    Redis集群水平擴展、集群中添加以及刪除節(jié)點的操作

    這篇文章主要介紹了Redis集群水平擴展、集群中添加以及刪除節(jié)點的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • redis持久化的介紹

    redis持久化的介紹

    今天小編就為大家分享一篇關(guān)于redis持久化的介紹,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Redis五種數(shù)據(jù)結(jié)構(gòu)在JAVA中如何封裝使用

    Redis五種數(shù)據(jù)結(jié)構(gòu)在JAVA中如何封裝使用

    本篇博文就針對Redis的五種數(shù)據(jù)結(jié)構(gòu)以及如何在JAVA中封裝使用做一個簡單的介紹。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-11-11
  • Redis GEO實現(xiàn)附近搜索功能

    Redis GEO實現(xiàn)附近搜索功能

    這篇文章主要介紹了Redis GEO實現(xiàn)附近搜索功能,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2024-12-12
  • Redis命令處理過程源碼解析

    Redis命令處理過程源碼解析

    這篇文章主要介紹了Redis命令處理過程源碼解析,本文是基于社區(qū)版redis4.0.8,通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-02-02

最新評論