You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Webflux与Kotlin中RedisLockRegistry使用问题及示例咨询

Webflux中使用RedisLockRegistry的示例与注意事项

1. 依赖配置

首先确保项目中引入必要的依赖(以Maven为例):

<dependencies>
    <!-- Reactive Redis 依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
    </dependency>
    <!-- Spring Integration Redis 提供RedisLockRegistry -->
    <dependency>
        <groupId>org.springframework.integration</groupId>
        <artifactId>spring-integration-redis</artifactId>
    </dependency>
</dependencies>

2. Redis连接与LockRegistry Bean定义

配置ReactiveRedisConnectionFactory,并创建RedisLockRegistry的Bean:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
import org.springframework.integration.redis.util.RedisLockRegistry;

import java.time.Duration;

@Configuration
public class RedisLockConfig {

    @Bean
    public RedisLockRegistry redisLockRegistry(ReactiveRedisConnectionFactory connectionFactory) {
        // 第一个参数:Redis连接工厂;第二个参数:锁的前缀(区分不同业务的锁)
        // 设置锁的默认过期时间(避免业务超时导致锁无法释放)
        RedisLockRegistry registry = new RedisLockRegistry(connectionFactory, "webflux-lock-prefix");
        registry.setExpireAfter(Duration.ofSeconds(30));
        return registry;
    }
}

3. Webflux中使用锁的示例

在非阻塞的Webflux服务中,禁止使用阻塞式的lock.lock()方法,需结合Reactor的API实现非阻塞锁获取与释放:

import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import java.util.concurrent.locks.Lock;

@Service
public class LockedService {

    private final RedisLockRegistry lockRegistry;

    public LockedService(RedisLockRegistry lockRegistry) {
        this.lockRegistry = lockRegistry;
    }

    public Mono<String> processWithLock(String businessKey) {
        // 根据业务key获取对应的锁
        Lock lock = lockRegistry.obtain(businessKey);

        // 非阻塞尝试获取锁,成功则执行业务,失败返回提示
        return Mono.fromCallable(lock::tryLock)
                .flatMap(lockAcquired -> {
                    if (lockAcquired) {
                        // 执行业务逻辑(非阻塞操作)
                        return handleBusinessLogic(businessKey)
                                .doFinally(signalType -> lock.unlock()); // 无论成功失败都释放锁
                    } else {
                        return Mono.just("当前业务正在处理中,请稍后重试");
                    }
                });
    }

    // 模拟非阻塞业务逻辑
    private Mono<String> handleBusinessLogic(String businessKey) {
        return Mono.just("处理业务: " + businessKey)
                .delayElement(Duration.ofSeconds(2)); // 模拟耗时操作
    }
}

在Webflux的Handler中调用:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

@RestController
public class LockController {

    private final LockedService lockedService;

    public LockController(LockedService lockedService) {
        this.lockedService = lockedService;
    }

    @GetMapping("/process/{key}")
    public Mono<String> process(@PathVariable String key) {
        return lockedService.processWithLock(key);
    }
}

锁获取失败的常见原因

  • 锁过期时间过短:业务处理时间超过锁的过期时间,导致锁被自动释放,后续请求可能获取到锁但业务冲突
  • 阻塞操作导致锁超时:在锁持有期间调用了阻塞API(如block()),导致线程被占用,无法及时释放锁
  • Redis连接问题:多个实例的Redis配置不一致(如不同的数据库、前缀),导致锁无法共享
  • 锁key冲突:不同业务使用了相同的锁key,导致不必要的锁竞争
  • 未正确释放锁:业务抛出异常时未执行unlock(),导致锁一直被持有(可通过doFinally确保释放)

内容的提问来源于stack exchange,提问作者user3241602

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 10:37:20