Spring早就提供了分布式锁的实现。原来分布式锁的相关代码存在于Spring Cloud的子项目Spring Cloud Cluster中,后来被迁到Spring Integration中。
Spring Integration为企业集成模式的实现;通俗地说,Spring Integration的定位是一个轻量级的ESB,尽管它做了很多ESB不做的事情。
当前Spring Integration提供的全局锁为以下存储提供了实现:
-
Gemfire
-
JDBC
-
Redis
-
Zookeeper
这些存储都使用相同的API抽象,因此无论使用哪种存储,你的编码过程是相同的,如想更换存储实现不需要更改代码,只需要修改依赖和配置即可。
新建项目结构如下:
-
引入pom依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.11</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>spring_integration</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring_integration</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <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> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>RELEASE</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2.修改配置文件增加redis配置
server: port: 8081 spring: redis: port: 6379 host: localhost
3.添加配置类
package com.mfc.springintegration.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.integration.redis.util.RedisLockRegistry; @Configuration public class RedisLockConfiguration { @Bean public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) { return new RedisLockRegistry(redisConnectionFactory, "svc-redis-lock"); } }
package com.mfc.springintegration.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.integration.redis.util.RedisLockRegistry; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; @RestController @RequestMapping(value = "redisLock") @Slf4j public class RedisLockController { @Autowired private RedisLockRegistry redisLockRegistry; @GetMapping("/t1") public void t1() throws InterruptedException { Lock lock = redisLockRegistry.obtain("lock"); boolean l1 = lock.tryLock(10, TimeUnit.SECONDS); log.info("t1-l1 = {}", l1); TimeUnit.SECONDS.sleep(15); boolean l2 = lock.tryLock(10, TimeUnit.SECONDS); log.info("t1-l2 = {}", l2); lock.unlock(); lock.unlock(); } @GetMapping("/t2") public void t2() throws InterruptedException { Lock lock = redisLockRegistry.obtain("lock"); boolean l1 = lock.tryLock(10, TimeUnit.SECONDS); log.info("t2-l1 = {}", l1); TimeUnit.SECONDS.sleep(15); boolean l2 = lock.tryLock(10, TimeUnit.SECONDS); log.info("t2-l2 = {}", l2); lock.unlock(); lock.unlock(); } }