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
相关产品推荐
相关产品推荐

