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

基于SpringBoot實現(xiàn)分布式鎖的三種方法

 更新時間:2025年12月12日 14:30:26   作者:IT界Tony哥  
這篇文章主要為大家詳細(xì)介紹了基于SpringBoot實現(xiàn)分布式鎖的三種方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

我來詳細(xì)講解Spring Boot中實現(xiàn)分布式鎖的幾種方式,包括手寫Redis鎖和使用Redisson框架。

一、基于Redis原生命令實現(xiàn)分布式鎖

1. 基礎(chǔ)版Redis分布式鎖

@Component
public class RedisDistributedLock {
    
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    private static final String LOCK_PREFIX = "distributed:lock:";
    private static final long DEFAULT_EXPIRE_TIME = 30000; // 30秒
    private static final long DEFAULT_WAIT_TIME = 10000;   // 10秒
    private static final long DEFAULT_SLEEP_TIME = 100;    // 100ms
    
    /**
     * 嘗試獲取分布式鎖(簡單版)
     * @param lockKey 鎖的key
     * @param value 鎖的值(通常用UUID)
     * @param expireTime 鎖的過期時間(ms)
     * @return 是否獲取成功
     */
    public boolean tryLock(String lockKey, String value, long expireTime) {
        String key = LOCK_PREFIX + lockKey;
        
        // 使用SET命令,通過NX參數(shù)實現(xiàn)"不存在時設(shè)置",EX參數(shù)設(shè)置過期時間
        Boolean result = redisTemplate.opsForValue()
            .setIfAbsent(key, value, expireTime, TimeUnit.MILLISECONDS);
        
        return Boolean.TRUE.equals(result);
    }
    
    /**
     * 釋放鎖
     * 需要確保是自己加的鎖才能釋放(防止釋放別人的鎖)
     */
    public boolean releaseLock(String lockKey, String value) {
        String key = LOCK_PREFIX + lockKey;
        String currentValue = redisTemplate.opsForValue().get(key);
        
        // 通過Lua腳本確保原子性:判斷值是否匹配,匹配則刪除
        String luaScript = 
            "if redis.call('get', KEYS[1]) == ARGV[1] then " +
            "   return redis.call('del', KEYS[1]) " +
            "else " +
            "   return 0 " +
            "end";
        
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText(luaScript);
        redisScript.setResultType(Long.class);
        
        Long result = redisTemplate.execute(
            redisScript, 
            Collections.singletonList(key), 
            value
        );
        
        return result != null && result == 1;
    }
    
    /**
     * 獲取鎖(支持重試)
     */
    public boolean lockWithRetry(String lockKey, String value, 
                                 long expireTime, long waitTime) {
        long endTime = System.currentTimeMillis() + waitTime;
        
        while (System.currentTimeMillis() < endTime) {
            if (tryLock(lockKey, value, expireTime)) {
                return true;
            }
            
            try {
                Thread.sleep(DEFAULT_SLEEP_TIME);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            }
        }
        
        return false;
    }
}

2. 可重入鎖實現(xiàn)

@Component
public class RedisReentrantLock {
    
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    private static final String LOCK_PREFIX = "reentrant:lock:";
    private static final ThreadLocal<Map<String, Integer>> LOCK_COUNT = 
        ThreadLocal.withInitial(HashMap::new);
    
    /**
     * 可重入鎖實現(xiàn)
     */
    public boolean tryReentrantLock(String lockKey, String clientId, 
                                    long expireTime) {
        String key = LOCK_PREFIX + lockKey;
        
        Map<String, Integer> lockCountMap = LOCK_COUNT.get();
        int count = lockCountMap.getOrDefault(lockKey, 0);
        
        // 重入:當(dāng)前線程已持有鎖
        if (count > 0) {
            lockCountMap.put(lockKey, count + 1);
            return true;
        }
        
        // 嘗試獲取鎖
        String luaScript = 
            "if redis.call('exists', KEYS[1]) == 0 then " +
            "   redis.call('hset', KEYS[1], 'owner', ARGV[1]) " +
            "   redis.call('hset', KEYS[1], 'count', 1) " +
            "   redis.call('pexpire', KEYS[1], ARGV[2]) " +
            "   return 1 " +
            "elseif redis.call('hget', KEYS[1], 'owner') == ARGV[1] then " +
            "   local count = redis.call('hget', KEYS[1], 'count') " +
            "   redis.call('hset', KEYS[1], 'count', tonumber(count) + 1) " +
            "   redis.call('pexpire', KEYS[1], ARGV[2]) " +
            "   return 1 " +
            "else " +
            "   return 0 " +
            "end";
        
        DefaultRedisScript<Long> script = new DefaultRedisScript<>();
        script.setScriptText(luaScript);
        script.setResultType(Long.class);
        
        Long result = redisTemplate.execute(
            script,
            Collections.singletonList(key),
            clientId,
            String.valueOf(expireTime)
        );
        
        if (result != null && result == 1) {
            lockCountMap.put(lockKey, 1);
            return true;
        }
        
        return false;
    }
    
    /**
     * 釋放可重入鎖
     */
    public boolean releaseReentrantLock(String lockKey, String clientId) {
        String key = LOCK_PREFIX + lockKey;
        
        Map<String, Integer> lockCountMap = LOCK_COUNT.get();
        int count = lockCountMap.getOrDefault(lockKey, 0);
        
        if (count <= 0) {
            return false;
        }
        
        if (count > 1) {
            // 重入次數(shù)減1
            lockCountMap.put(lockKey, count - 1);
            return true;
        }
        
        // 最后一次重入,釋放鎖
        String luaScript = 
            "if redis.call('hget', KEYS[1], 'owner') == ARGV[1] then " +
            "   local current = redis.call('hget', KEYS[1], 'count') " +
            "   if tonumber(current) > 1 then " +
            "       redis.call('hset', KEYS[1], 'count', tonumber(current) - 1) " +
            "       redis.call('pexpire', KEYS[1], ARGV[2]) " +
            "       return 0 " +
            "   else " +
            "       redis.call('del', KEYS[1]) " +
            "       return 1 " +
            "   end " +
            "else " +
            "   return -1 " +
            "end";
        
        DefaultRedisScript<Long> script = new DefaultRedisScript<>();
        script.setScriptText(luaScript);
        script.setResultType(Long.class);
        
        Long result = redisTemplate.execute(
            script,
            Collections.singletonList(key),
            clientId,
            "30000"
        );
        
        if (result != null && result == 1) {
            lockCountMap.remove(lockKey);
            if (lockCountMap.isEmpty()) {
                LOCK_COUNT.remove();
            }
            return true;
        }
        
        return false;
    }
}

二、使用Redisson實現(xiàn)分布式鎖(推薦生產(chǎn)環(huán)境使用)

1. 添加依賴

<!-- pom.xml -->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.23.5</version>
</dependency>

2. 配置Redisson

# application.yml
spring:
  redis:
    host: localhost
    port: 6379
    database: 0
    timeout: 3000

redisson:
  config: |
    singleServerConfig:
      address: "redis://${spring.redis.host}:${spring.redis.port}"
      database: ${spring.redis.database}
      connectionPoolSize: 64
      connectionMinimumIdleSize: 24
      idleConnectionTimeout: 10000
      connectTimeout: ${spring.redis.timeout}
      timeout: ${spring.redis.timeout}
      retryAttempts: 3
      retryInterval: 1500

3. Redisson分布式鎖服務(wù)

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public class RedissonDistributedLock {
    
    @Autowired
    private RedissonClient redissonClient;
    
    /**
     * 可重入鎖(最常用)
     */
    public boolean tryReentrantLock(String lockKey, long waitTime, 
                                    long leaseTime, TimeUnit unit) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, unit);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
    }
    
    /**
     * 公平鎖
     */
    public boolean tryFairLock(String lockKey, long waitTime, 
                               long leaseTime, TimeUnit unit) {
        RLock lock = redissonClient.getFairLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, unit);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
    }
    
    /**
     * 聯(lián)鎖(多個鎖同時獲?。?
     */
    public boolean tryMultiLock(String[] lockKeys, long waitTime, 
                                long leaseTime, TimeUnit unit) {
        RLock[] locks = new RLock[lockKeys.length];
        for (int i = 0; i < lockKeys.length; i++) {
            locks[i] = redissonClient.getLock(lockKeys[i]);
        }
        
        RLock multiLock = redissonClient.getMultiLock(locks);
        try {
            return multiLock.tryLock(waitTime, leaseTime, unit);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
    }
    
    /**
     * 紅鎖(RedLock,多個Redis實例)
     */
    public boolean tryRedLock(String lockKey, long waitTime, 
                              long leaseTime, TimeUnit unit) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, unit);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
    }
    
    /**
     * 釋放鎖
     */
    public void unlock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        if (lock.isLocked() && lock.isHeldByCurrentThread()) {
            lock.unlock();
        }
    }
    
    /**
     * 強(qiáng)制釋放鎖
     */
    public void forceUnlock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.forceUnlock();
    }
    
    /**
     * 自動續(xù)期的鎖(看門狗機(jī)制)
     */
    public void lockWithWatchdog(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock(); // 默認(rèn)30秒,看門狗會自動續(xù)期
    }
}

4. 使用AOP簡化分布式鎖使用

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DistributedLock {
    
    /** 鎖的key,支持SpEL表達(dá)式 */
    String key();
    
    /** 鎖類型,默認(rèn)可重入鎖 */
    LockType lockType() default LockType.REENTRANT;
    
    /** 等待時間(秒) */
    long waitTime() default 5;
    
    /** 持有時間(秒),-1表示使用看門狗自動續(xù)期 */
    long leaseTime() default -1;
    
    /** 時間單位 */
    TimeUnit timeUnit() default TimeUnit.SECONDS;
    
    enum LockType {
        REENTRANT,      // 可重入鎖
        FAIR,           // 公平鎖
        READ,           // 讀鎖
        WRITE,          // 寫鎖
        MULTI,          // 聯(lián)鎖
        RED             // 紅鎖
    }
}
@Aspect
@Component
@Slf4j
public class DistributedLockAspect {
    
    @Autowired
    private RedissonClient redissonClient;
    
    @Autowired
    private RedissonDistributedLock redissonDistributedLock;
    
    @Around("@annotation(distributedLock)")
    public Object around(ProceedingJoinPoint joinPoint, 
                         DistributedLock distributedLock) throws Throwable {
        String lockKey = parseKey(distributedLock.key(), joinPoint);
        RLock lock = getLock(lockKey, distributedLock.lockType());
        
        boolean locked = false;
        try {
            // 嘗試獲取鎖
            if (distributedLock.leaseTime() == -1) {
                // 使用看門狗自動續(xù)期
                lock.lock();
            } else {
                locked = lock.tryLock(
                    distributedLock.waitTime(),
                    distributedLock.leaseTime(),
                    distributedLock.timeUnit()
                );
            }
            
            if (!locked && distributedLock.leaseTime() != -1) {
                throw new RuntimeException("獲取分布式鎖失敗: " + lockKey);
            }
            
            log.info("獲取分布式鎖成功: {}", lockKey);
            return joinPoint.proceed();
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("獲取分布式鎖被中斷", e);
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
                log.info("釋放分布式鎖: {}", lockKey);
            }
        }
    }
    
    private String parseKey(String keySpEL, ProceedingJoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        
        // 解析SpEL表達(dá)式
        if (keySpEL.startsWith("#")) {
            ExpressionParser parser = new SpelExpressionParser();
            Expression expression = parser.parseExpression(keySpEL);
            
            EvaluationContext context = new StandardEvaluationContext();
            context.setVariable("methodName", method.getName());
            
            // 設(shè)置參數(shù)
            Object[] args = joinPoint.getArgs();
            Parameter[] parameters = method.getParameters();
            for (int i = 0; i < parameters.length; i++) {
                context.setVariable(parameters[i].getName(), args[i]);
            }
            
            return expression.getValue(context, String.class);
        }
        
        return keySpEL;
    }
    
    private RLock getLock(String lockKey, DistributedLock.LockType lockType) {
        switch (lockType) {
            case FAIR:
                return redissonClient.getFairLock(lockKey);
            case READ:
                return redissonClient.getReadWriteLock(lockKey).readLock();
            case WRITE:
                return redissonClient.getReadWriteLock(lockKey).writeLock();
            case MULTI:
            case RED:
                // 簡化處理,實際使用需要多個實例
                return redissonClient.getLock(lockKey);
            case REENTRANT:
            default:
                return redissonClient.getLock(lockKey);
        }
    }
}

三、使用Spring Integration實現(xiàn)分布式鎖

1. 添加依賴

<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>

2. 配置Redis鎖注冊表

@Configuration
public class RedisLockConfiguration {
    
    @Bean
    public RedisLockRegistry redisLockRegistry(RedisConnectionFactory connectionFactory) {
        // 過期時間10秒
        return new RedisLockRegistry(connectionFactory, "distributed-lock", 10000L);
    }
    
    @Bean
    public LockRegistry lockRegistry(RedisLockRegistry redisLockRegistry) {
        return redisLockRegistry;
    }
}

3. 使用Spring Integration鎖

@Service
@Slf4j
public class OrderService {
    
    @Autowired
    private LockRegistry lockRegistry;
    
    public void createOrder(String orderId) {
        Lock lock = lockRegistry.obtain("order:" + orderId);
        
        boolean locked = false;
        try {
            // 嘗試獲取鎖,最多等待5秒
            locked = lock.tryLock(5, TimeUnit.SECONDS);
            
            if (!locked) {
                throw new RuntimeException("系統(tǒng)繁忙,請稍后重試");
            }
            
            // 執(zhí)行業(yè)務(wù)邏輯
            processOrder(orderId);
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("訂單處理被中斷", e);
        } finally {
            if (locked) {
                lock.unlock();
            }
        }
    }
    
    private void processOrder(String orderId) {
        // 訂單處理邏輯
        log.info("處理訂單: {}", orderId);
    }
}

四、實際應(yīng)用示例

1. 商品秒殺場景

@Service
@Slf4j
public class SeckillService {
    
    @Autowired
    private RedissonClient redissonClient;
    
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    private static final String SECKILL_PREFIX = "seckill:product:";
    private static final String LOCK_PREFIX = "seckill:lock:";
    
    /**
     * 秒殺下單(防超賣)
     */
    public boolean seckillOrder(Long productId, Integer quantity, Long userId) {
        String lockKey = LOCK_PREFIX + productId;
        RLock lock = redissonClient.getLock(lockKey);
        
        try {
            // 嘗試獲取鎖,等待100ms,持有鎖3秒
            if (!lock.tryLock(100, 3000, TimeUnit.MILLISECONDS)) {
                throw new RuntimeException("搶購太火爆,請重試");
            }
            
            // 檢查庫存
            String stockKey = SECKILL_PREFIX + productId + ":stock";
            Integer stock = Integer.valueOf(
                redisTemplate.opsForValue().get(stockKey)
            );
            
            if (stock == null || stock < quantity) {
                throw new RuntimeException("庫存不足");
            }
            
            // 扣減庫存
            Long newStock = redisTemplate.opsForValue().decrement(stockKey, quantity);
            if (newStock < 0) {
                // 庫存不足,恢復(fù)庫存
                redisTemplate.opsForValue().increment(stockKey, quantity);
                throw new RuntimeException("庫存不足");
            }
            
            // 創(chuàng)建訂單
            createOrder(productId, quantity, userId);
            
            return true;
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("系統(tǒng)異常", e);
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
    
    /**
     * 使用注解簡化版
     */
    @DistributedLock(
        key = "'seckill:lock:' + #productId",
        waitTime = 1,
        leaseTime = 3,
        timeUnit = TimeUnit.SECONDS
    )
    public boolean seckillOrderWithAnnotation(Long productId, Integer quantity, Long userId) {
        // 業(yè)務(wù)邏輯,無需關(guān)心鎖的獲取和釋放
        String stockKey = SECKILL_PREFIX + productId + ":stock";
        Integer stock = Integer.valueOf(
            redisTemplate.opsForValue().get(stockKey)
        );
        
        if (stock == null || stock < quantity) {
            throw new RuntimeException("庫存不足");
        }
        
        Long newStock = redisTemplate.opsForValue().decrement(stockKey, quantity);
        if (newStock < 0) {
            redisTemplate.opsForValue().increment(stockKey, quantity);
            throw new RuntimeException("庫存不足");
        }
        
        createOrder(productId, quantity, userId);
        return true;
    }
    
    private void createOrder(Long productId, Integer quantity, Long userId) {
        // 創(chuàng)建訂單邏輯
        log.info("用戶{}搶購商品{},數(shù)量{}", userId, productId, quantity);
    }
}

2. 定時任務(wù)防重復(fù)執(zhí)行

@Component
@Slf4j
public class ScheduledTasks {
    
    @Autowired
    private RedissonClient redissonClient;
    
    /**
     * 分布式定時任務(wù),確保集群中只有一個實例執(zhí)行
     */
    @Scheduled(cron = "0 */5 * * * ?") // 每5分鐘執(zhí)行一次
    public void syncDataTask() {
        String lockKey = "task:sync:data";
        RLock lock = redissonClient.getLock(lockKey);
        
        // 不等待,獲取不到鎖直接返回
        boolean locked = lock.tryLock();
        if (!locked) {
            log.info("其他節(jié)點正在執(zhí)行數(shù)據(jù)同步任務(wù)");
            return;
        }
        
        try {
            log.info("開始執(zhí)行數(shù)據(jù)同步任務(wù)");
            // 執(zhí)行業(yè)務(wù)邏輯
            syncData();
            log.info("數(shù)據(jù)同步任務(wù)完成");
        } finally {
            lock.unlock();
        }
    }
    
    private void syncData() {
        // 數(shù)據(jù)同步邏輯
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

五、配置和最佳實踐

1. Redisson配置類

@Configuration
public class RedissonConfig {
    
    @Value("${spring.redis.host}")
    private String redisHost;
    
    @Value("${spring.redis.port}")
    private String redisPort;
    
    @Value("${spring.redis.password:}")
    private String password;
    
    @Value("${spring.redis.database:0}")
    private int database;
    
    @Bean(destroyMethod = "shutdown")
    public RedissonClient redissonClient() {
        Config config = new Config();
        
        // 單節(jié)點模式
        config.useSingleServer()
            .setAddress(String.format("redis://%s:%s", redisHost, redisPort))
            .setDatabase(database)
            .setPassword(StringUtils.hasText(password) ? password : null)
            .setConnectionPoolSize(64)
            .setConnectionMinimumIdleSize(10)
            .setIdleConnectionTimeout(10000)
            .setConnectTimeout(3000)
            .setTimeout(3000)
            .setRetryAttempts(3)
            .setRetryInterval(1500)
            .setPingConnectionInterval(30000)
            .setKeepAlive(true);
        
        // 鎖配置
        config.setLockWatchdogTimeout(30000L); // 看門狗超時時間
        
        return Redisson.create(config);
    }
}

2. 分布式鎖工具類

@Component
@Slf4j
public class DistributedLockUtil {
    
    @Autowired
    private RedissonClient redissonClient;
    
    /**
     * 執(zhí)行帶鎖的方法
     */
    public <T> T executeWithLock(String lockKey, long waitTime, long leaseTime, 
                                  TimeUnit unit, Supplier<T> supplier) {
        RLock lock = redissonClient.getLock(lockKey);
        boolean locked = false;
        
        try {
            locked = lock.tryLock(waitTime, leaseTime, unit);
            if (!locked) {
                throw new DistributedLockException("獲取分布式鎖失敗: " + lockKey);
            }
            
            return supplier.get();
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new DistributedLockException("獲取分布式鎖被中斷", e);
        } finally {
            if (locked && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
    
    /**
     * 執(zhí)行帶鎖的方法(無返回值)
     */
    public void executeWithLock(String lockKey, long waitTime, long leaseTime,
                               TimeUnit unit, Runnable runnable) {
        executeWithLock(lockKey, waitTime, leaseTime, unit, () -> {
            runnable.run();
            return null;
        });
    }
    
    /**
     * 執(zhí)行帶鎖的方法(快速失敗)
     */
    public <T> Optional<T> tryExecuteWithLock(String lockKey, long waitTime, 
                                             long leaseTime, TimeUnit unit,
                                             Supplier<T> supplier) {
        try {
            return Optional.ofNullable(
                executeWithLock(lockKey, waitTime, leaseTime, unit, supplier)
            );
        } catch (DistributedLockException e) {
            log.warn("獲取鎖失敗,跳過執(zhí)行: {}", lockKey);
            return Optional.empty();
        }
    }
    
    public static class DistributedLockException extends RuntimeException {
        public DistributedLockException(String message) {
            super(message);
        }
        
        public DistributedLockException(String message, Throwable cause) {
            super(message, cause);
        }
    }
}

六、測試分布式鎖

@SpringBootTest
@Slf4j
class DistributedLockTest {
    
    @Autowired
    private RedissonDistributedLock redissonDistributedLock;
    
    @Autowired
    private DistributedLockUtil distributedLockUtil;
    
    private final AtomicInteger counter = new AtomicInteger(0);
    
    @Test
    void testConcurrentLock() throws InterruptedException {
        int threadCount = 10;
        String lockKey = "test:concurrent:lock";
        CountDownLatch latch = new CountDownLatch(threadCount);
        
        ExecutorService executor = Executors.newFixedThreadPool(threadCount);
        
        for (int i = 0; i < threadCount; i++) {
            executor.submit(() -> {
                try {
                    boolean locked = redissonDistributedLock
                        .tryReentrantLock(lockKey, 2, 5, TimeUnit.SECONDS);
                    
                    if (locked) {
                        try {
                            // 模擬業(yè)務(wù)處理
                            Thread.sleep(100);
                            int value = counter.incrementAndGet();
                            log.info("線程 {} 獲取鎖成功,計數(shù): {}", 
                                    Thread.currentThread().getName(), value);
                        } finally {
                            redissonDistributedLock.unlock(lockKey);
                        }
                    } else {
                        log.warn("線程 {} 獲取鎖失敗", Thread.currentThread().getName());
                    }
                } catch (Exception e) {
                    log.error("線程執(zhí)行異常", e);
                } finally {
                    latch.countDown();
                }
            });
        }
        
        latch.await();
        executor.shutdown();
        
        assertEquals(threadCount, counter.get());
    }
    
    @Test
    void testLockWithUtil() {
        String lockKey = "test:util:lock";
        
        String result = distributedLockUtil.executeWithLock(
            lockKey, 
            2, 
            5, 
            TimeUnit.SECONDS,
            () -> {
                // 業(yè)務(wù)邏輯
                return "success";
            }
        );
        
        assertEquals("success", result);
    }
}

總結(jié)與建議

1.選擇方案

  • 簡單場景:使用Spring Integration的RedisLockRegistry
  • 生產(chǎn)環(huán)境:推薦使用Redisson,功能最全,穩(wěn)定性最好
  • 特殊需求:需要精細(xì)控制時,可以使用原生Redis命令自定義

2.最佳實踐

  • 鎖的key要有業(yè)務(wù)含義,如order:create:{orderId}
  • 一定要設(shè)置合理的過期時間,防止死鎖
  • 釋放鎖時要檢查是否當(dāng)前線程持有
  • 使用Lua腳本保證原子性
  • 考慮鎖的可重入性
  • 生產(chǎn)環(huán)境使用Redis集群或哨兵模式

3.注意事項

  • 避免鎖粒度過大,影響并發(fā)性能
  • 避免鎖持有時間過長
  • 實現(xiàn)鎖的自動續(xù)期(看門狗機(jī)制)
  • 考慮鎖等待超時和快速失敗
  • 添加監(jiān)控和告警機(jī)制

4.常見問題解決

  • 鎖提前過期:使用Redisson的看門狗機(jī)制
  • 鎖誤刪:每個鎖設(shè)置唯一value,釋放時驗證
  • 鎖不可重入:使用Redisson或?qū)崿F(xiàn)可重入邏輯
  • Redis集群故障:使用RedLock算法(多個Redis實例)

這樣實現(xiàn)的分布式鎖既安全又可靠,可以滿足大多數(shù)業(yè)務(wù)場景的需求。

以上就是基于SpringBoot實現(xiàn)分布式鎖的三種方法的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot分布式鎖的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java使用Logback配置輸出日志內(nèi)容到文件示例代碼

    java使用Logback配置輸出日志內(nèi)容到文件示例代碼

    這篇文章主要介紹了java?Logback輸出日志內(nèi)容到文件,要將logger.info的信息輸出到文件,您可以使用Logback配置,本文通過實例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • spring緩存自定義resolver的方法

    spring緩存自定義resolver的方法

    這篇文章主要為大家詳細(xì)介紹了spring緩存自定義resolver的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • java簡單工廠模式實例及講解

    java簡單工廠模式實例及講解

    這篇文章主要為大家詳細(xì)介紹了java簡單工廠模式實例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • java中實現(xiàn)OCR文字提取的幾個常用工具(Tesseract、PaddleOCR及RapidOCR)

    java中實現(xiàn)OCR文字提取的幾個常用工具(Tesseract、PaddleOCR及RapidOCR)

    Java最強(qiáng)的OCR識別是指在Java開發(fā)環(huán)境下,具有強(qiáng)大OCR(Optical Character Recognition,光學(xué)字符識別)功能的工具或庫,這篇文章主要介紹了java中實現(xiàn)OCR文字提取的幾種方法,分別是Tesseract、PaddleOCR及RapidOCR,需要的朋友可以參考下
    2025-09-09
  • IDEA JetBrains Mono字體介紹和安裝教程(詳解)

    IDEA JetBrains Mono字體介紹和安裝教程(詳解)

    這篇文章主要介紹了IDEA JetBrains Mono字體介紹和安裝教程,本給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • Java SpringBoot 集成 Redis詳解

    Java SpringBoot 集成 Redis詳解

    Redis 是一個由 Salvatore Sanfilippo 寫的 key-value 存儲系統(tǒng),是跨平臺的非關(guān)系型數(shù)據(jù)庫。Redis 是一個開源的使用 ANSI C 語言編寫、遵守 BSD 協(xié)議、支持網(wǎng)絡(luò)、可基于內(nèi)存、分布式、可選持久性的鍵值對(Key-Value)存儲數(shù)據(jù)庫,并提供多種語言的 API
    2021-10-10
  • spring boot實戰(zhàn)之本地jar包引用示例

    spring boot實戰(zhàn)之本地jar包引用示例

    本篇文章主要介紹了spring boot實戰(zhàn)之本地jar包引用示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • MyBatis實現(xiàn)數(shù)據(jù)庫類型和Java類型的轉(zhuǎn)換

    MyBatis實現(xiàn)數(shù)據(jù)庫類型和Java類型的轉(zhuǎn)換

    MyBatis 在處理數(shù)據(jù)庫查詢結(jié)果或傳遞參數(shù)時,需要將數(shù)據(jù)庫類型與 Java 類型之間進(jìn)行轉(zhuǎn)換,本文就給大家介紹MyBatis如何實現(xiàn)數(shù)據(jù)庫類型和 Java 類型的轉(zhuǎn)換的,需要的朋友可以參考下
    2024-09-09
  • CompletableFuture創(chuàng)建及功能使用全面詳解

    CompletableFuture創(chuàng)建及功能使用全面詳解

    這篇文章主要為大家介紹了CompletableFuture創(chuàng)建及功能使用全面詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • 拳皇(Java簡單的小程序)代碼實例

    拳皇(Java簡單的小程序)代碼實例

    這篇文章主要介紹了拳皇Java簡單小程序,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03

最新評論

井冈山市| 平塘县| 梁平县| 静海县| 汝州市| 苍梧县| 富民县| 蒙阴县| 璧山县| 太白县| 娄烦县| 江华| 大同市| 高碑店市| 永城市| 临安市| 屏南县| 桐庐县| 科技| 黔西| 贵定县| 东丰县| 房山区| 大埔县| 灵寿县| 康定县| 安新县| 正宁县| 铜鼓县| 运城市| 冀州市| 谢通门县| 益阳市| 苗栗县| 盐边县| 晋城| 新化县| 英吉沙县| 贵港市| 云南省| 和田县|