Redis实现分布式锁

分布式锁的实现方案

Spring早就提供了分布式锁的实现,早期,分布式锁的相关代码存在与Spring Cloud的子项目Spring Cloud Cluster中,后来被迁移到了Spring Integration中。

Spring Cloud Cluster的GitHub:https://github.com/spring-cloud/spring-cloud-cluster/

Spring Integration的GitHub:https://github.com/spring-projects/spring-integration/

官方对于Spring Integration的说法是 这是一个企业集成模式的实现。Spring Cloud Stream的底层也是Spring Integration

Spring Integration提供了多种全局锁,现在我们在这里只介绍基于Redis的分布式锁

基于Spring Integration 实现Redis的分布式锁

1.依赖

1
2
3
4
5
6
7
8
9
10
11
12
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.Redis配置

1
2
3
4
spring:
redis:
port: 6379
host: localhost

3.RedisLock初始化

1
2
3
4
5
6
7
@Configuration
public class RedisLockConfiguration {
@Bean
public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) {
return new RedisLockRegistry(redisConnectionFactory, "RedisLockRegistry");
}
}

org.springframework.integration.redis.util.RedisLockRegistry的注释详细描述了该类的特性以及使用方式。

4.测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* @author Mr.zhang
* @description
* @date 1:43 PM 2019/3/26
*/
@Slf4j
@RestController
@RequestMapping("redisLock")
public class RedisLockController {

@Autowired
private RedisLockRegistry redisLockRegistry;

@GetMapping("test")
public void test() throws InterruptedException {
Lock lock = redisLockRegistry.obtain("redisLock");
boolean b1 = lock.tryLock(3, TimeUnit.SECONDS);
log.info("b1 is : {}", b1);

TimeUnit.SECONDS.sleep(5);

boolean b2 = lock.tryLock(3, TimeUnit.SECONDS);
log.info("b2 is : {}", b2);

lock.unlock();
lock.unlock();
}
}
  • 启动1个实例,访问 http://localhost:8080/redisLock/test ,会看到类似如下的日志
1
2
2019-03-26 14:42:28.206  INFO 4913 --- [nio-8080-exec-1] c.r.lock.controller.RedisLockController  : b1 is : true
2019-03-26 14:42:33.212 INFO 4913 --- [nio-8080-exec-1] c.r.lock.controller.RedisLockController : b2 is : true
  • 启动2个实例,并迅速访问两个实例的 /test 端点,会在第二个实例上看到类似如下日志
1
2
3
4
5
6
7
8
[nio-8081-exec-1] c.r.lock.controller.RedisLockController  : b1 is : false
[nio-8081-exec-1] c.r.lock.controller.RedisLockController : b2 is : true
[nio-8081-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() ...

java.lang.IllegalStateException: You do not own lock at RedisLockRegistry:redisLock
at org.springframework.integration.redis.util.RedisLockRegistry$RedisLock.unlock(RedisLockRegistry.java:300) ~[spring-integration-redis-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at com.redis.lock.controller.RedisLockController.test(RedisLockController.java:38) ~[classes!/:0.0.1-SNAPSHOT]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_144]

​ 说明第二个实例没有拿到锁,证明了分布式锁的存在

参考地址