基于SpringBoot实现分布式锁的三种方法

2025-12-12 19:50

本文主要是介绍基于SpringBoot实现分布式锁的三种方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《基于SpringBoot实现分布式锁的三种方法》这篇文章主要为大家详细介绍了基于SpringBoot实现分布式锁的三种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下...

我来详细讲解Spring Boot中实现分布式锁的几种方式,包括手写Redis锁和使用Redisson框架。

一、基于Redis原生命令实现分布式锁

1. 基础版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参数实现"不存在时设置",EX参数设置过期时间
        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. 可重入锁实现

@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);
    
    /**
     * 可重入锁实现
     */
    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);
        
        // 重入:当前线程已持有锁
        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) {
            // 重入次数减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实现分布式锁(推荐生产环境使用)

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
      rChina编程etryInterval: 1500

3. Redisson分布式锁服务

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;
        }
    }
    
    /**
     * 联锁(多个锁同时获取)
     *android/
    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();
        }
    }
    
    /**
     * 强制释放锁
     */
    public void forceUnlock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.forceUnlock();
    }
    
    /**
     * 自动续期的锁(看门狗机制)
     */
    public void lockWithWatchdog(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock(); // 默认30秒,看门狗会自动续期
    }
}

4. 使用AOP简化分布式锁使用

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DistributedLock {
    
    /** 锁的key,支持SpEL表达式 */
    String key();
    
    /** 锁类型,默认可重入锁 */
    LockType lockType() default LockType.REENTRANT;
    
    /** 等待时间(秒) */
    long waitTime() default 5;
    
    /** 持有时间(秒),-1表示使用看门狗自动续期 */
    long leaseTime() default -1;
    
    /** 时间单位 */
    TimeUnit timeUnit() default TimeUnit.SECONDS;
    
    enum LockType {
        REENTRANT,      // 可重入锁
        FAIR,           // 公平锁
        READ,           // 读锁
        WRITE,          // 写锁
        MULTI,          // 联锁
        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) {
                // 使用看门狗自动续期
                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表达式
        if (keySpEL.startsWith("#")) {
            ExpressionParser parser = new SpelExpressionParser();
            Expression expression = parser.parseExpression(keySpEL);
            
            EvaluationContext context = new StandardEvaluationContext();
            context.setVariable("methodName", method.getName());
            
            // 设置参数
            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实现分布式锁

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 lockedpython = false;
        try {
            // 尝试获取锁,最多等待5秒
            locked = lock.tryLock(5, TimeUnit.SECONDS);
            
            if (!locked) {
                throw new RuntimeException("系统繁忙,请稍后重试");
            }
            
            // 执行业务逻辑
            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);
    }
}

四、实际应用示例

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) {
                // 库存不足,恢复库存
                redisTemplate.opsForValue().increment(stockKey, quantity);
                throw new RuntimeException("库存不足");
            }
            
            // 创建订单
            createOrder(productId, quantity, userId);
            
            return true;
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("系统异常", 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) {
        // 业务逻辑,无需关心锁的获取和释放
        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 (newStwww.chinasem.cnock < 0) {
            redisTemplate.opsForValue().increment(stockKey, quantity);
            throw new RuntimeException("库存不足");
        }
        
        createOrder(productId, quantity, userId);
        return true;
    }
    
    private void createOrder(Long productId, Integer quantity, Long userId) {
        // 创建订单逻辑
        log.info("用户{}抢购商品{},数量{}", userId, productId, quantity);
    }
}

2. 定时任务防重复执行

@Component
@Slf4j
public class ScheduledTasks {
    
    @Autowired
    private RedissonClient redissonClient;
    
    /**
     * 分布式定时任务,确保集群中只有一个实例执行
     */
    @Scheduled(cron = "0 */5 * * * ?") // 每5分钟执行一次
    public void syncDataTask() {
        String lockKey = "task:sync:data";
        RLock lock = redissonClient.getLock(lockKey);
        
        // 不等待,获取不到锁直接返回
        boolean locked = lock.tryLock();
        if (!locked) {
            log.info("其他节点正在执行数据同步任务");
            return;
        }
        
        try {
            log.info("开始执行数据同步任务");
            // 执行业务逻辑
            syncData();
            log.info("数据同步任务完成");
        } finally {
            lock.unlock();
        }
    }
    
    private void syncData() {
        // 数据同步逻辑
        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();
        
        // 单节点模式
        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;
    
    /**
     * 执行带锁的方法
     */
    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();
            }
        }
    }
    
    /**
     * 执行带锁的方法(无返回值)
     */
    public void executeWithLock(String lockKey, long waitTime, long leaseTime,
                               TimeUnit unit, Runnable runnable) {
        executeWithLock(lockKey, waitTime, leaseTime, unit, () -> {
            runnable.run();
            return null;
        });
    }
    
    /**
     * 执行带锁的方法(快速失败)
     */
    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("获取锁失败,跳过执行: {}", 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);
                    
        编程China编程            if (locked) {
                        try {
                            // 模拟业务处理
                            Thread.sleep(100);
                            int value = counter.incrementAndGet();
                            log.info("线程 {} 获取锁成功,计数: {}", 
                                    Thread.currentThread().getName(), value);
                        } finally {
                            redissonDistributedLock.unlock(lockKey);
                        }
                    } else {
                        log.warn("线程 {} 获取锁失败", Thread.currentThread().getName());
                    }
                } catch (Exception e) {
                    log.error("线程执行异常", 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,
            () -> {
                // 业务逻辑
                return "success";
            }
        );
        
        assertEquals("success", result);
    }
}

总结与建议

1.选择方案

  • 简单场景:使用Spring Integration的RedisLockRegistry
  • 生产环境:推荐使用Redisson,功能最全,稳定性最好
  • 特殊需求:需要精细控制时,可以使用原生Redis命令自定义

2.最佳实践

  • 锁的key要有业务含义,如order:create:{orderId}
  • 一定要设置合理的过期时间,防止死锁
  • 释放锁时要检查是否当前线程持有
  • 使用Lua脚本保证原子性
  • 考虑锁的可重入性
  • 生产环境使用Redis集群或哨兵模式

3.注意事项

  • 避免锁粒度过大,影响并发性能
  • 避免锁持有时间过长
  • 实现锁的自动续期(看门狗机制)
  • 考虑锁等待超时和快速失败
  • 添加监控和告警机制

4.常见问题解决

  • 锁提前过期:使用Redisson的看门狗机制
  • 锁误删:每个锁设置唯一value,释放时验证
  • 锁不可重入:使用Redisson或实现可重入逻辑
  • Redis集群故障:使用RedLock算法(多个Redis实例)

这样实现的分布式锁既安全又可靠,可以满足大多数业务场景的需求。

以上就是基于SpringBoot实现分布式锁的三种方法的详细内容,更多关于SpringBoot分布式锁的资料请关注China编程(www.chinasem.cn)其它相关文章!

这篇关于基于SpringBoot实现分布式锁的三种方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1156432

相关文章

springboot+redis实现订单过期(超时取消)功能的方法详解

《springboot+redis实现订单过期(超时取消)功能的方法详解》在SpringBoot中使用Redis实现订单过期(超时取消)功能,有多种成熟方案,本文为大家整理了几个详细方法,文中的示例代... 目录一、Redis键过期回调方案(推荐)1. 配置Redis监听器2. 监听键过期事件3. Redi

Spring Boot 处理带文件表单的方式汇总

《SpringBoot处理带文件表单的方式汇总》本文详细介绍了六种处理文件上传的方式,包括@RequestParam、@RequestPart、@ModelAttribute、@ModelAttr... 目录方式 1:@RequestParam接收文件后端代码前端代码特点方式 2:@RequestPart接

SpringBoot整合Zuul全过程

《SpringBoot整合Zuul全过程》Zuul网关是微服务架构中的重要组件,具备统一入口、鉴权校验、动态路由等功能,它通过配置文件进行灵活的路由和过滤器设置,支持Hystrix进行容错处理,还提供... 目录Zuul网关的作用Zuul网关的应用1、网关访问方式2、网关依赖注入3、网关启动器4、网关全局变

SpringBoot全局异常拦截与自定义错误页面实现过程解读

《SpringBoot全局异常拦截与自定义错误页面实现过程解读》本文介绍了SpringBoot中全局异常拦截与自定义错误页面的实现方法,包括异常的分类、SpringBoot默认异常处理机制、全局异常拦... 目录一、引言二、Spring Boot异常处理基础2.1 异常的分类2.2 Spring Boot默

SpringBoo WebFlux+MongoDB实现非阻塞API过程

《SpringBooWebFlux+MongoDB实现非阻塞API过程》本文介绍了如何使用SpringBootWebFlux和MongoDB实现非阻塞API,通过响应式编程提高系统的吞吐量和响应性能... 目录一、引言二、响应式编程基础2.1 响应式编程概念2.2 响应式编程的优势2.3 响应式编程相关技术

SpringBoot的全局异常拦截实践过程

《SpringBoot的全局异常拦截实践过程》SpringBoot中使用@ControllerAdvice和@ExceptionHandler实现全局异常拦截,@RestControllerAdvic... 目录@RestControllerAdvice@ResponseStatus(...)@Except

Springboot配置文件相关语法及读取方式详解

《Springboot配置文件相关语法及读取方式详解》本文主要介绍了SpringBoot中的两种配置文件形式,即.properties文件和.yml/.yaml文件,详细讲解了这两种文件的语法和读取方... 目录配置文件的形式语法1、key-value形式2、数组形式读取方式1、通过@value注解2、通过

Java 接口定义变量的示例代码

《Java接口定义变量的示例代码》文章介绍了Java接口中的变量和方法,接口中的变量必须是publicstaticfinal的,用于定义常量,而方法默认是publicabstract的,必须由实现类... 在 Java 中,接口是一种抽象类型,用于定义类必须实现的方法。接口可以包含常量和方法,但不能包含实例

JAVA Calendar设置上个月时,日期不存在或错误提示问题及解决

《JAVACalendar设置上个月时,日期不存在或错误提示问题及解决》在使用Java的Calendar类设置上个月的日期时,如果遇到不存在的日期(如4月31日),默认会自动调整到下个月的相应日期(... 目录Java Calendar设置上个月时,日期不存在或错误提示java进行日期计算时如果出现不存在的

C#实现将XML数据自动化地写入Excel文件

《C#实现将XML数据自动化地写入Excel文件》在现代企业级应用中,数据处理与报表生成是核心环节,本文将深入探讨如何利用C#和一款优秀的库,将XML数据自动化地写入Excel文件,有需要的小伙伴可以... 目录理解XML数据结构与Excel的对应关系引入高效工具:使用Spire.XLS for .NETC