├── redis-distributed-lock-starter-demo ├── readme.md ├── .gitignore ├── src │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── snowalker │ │ │ └── RedisDistributedLockStarterDemoApplicationTests.java │ └── main │ │ ├── java │ │ └── com │ │ │ └── snowalker │ │ │ ├── RedisDistributedLockStarterDemoApplication.java │ │ │ └── executor │ │ │ ├── ExecutorRedissonAnnotation.java │ │ │ └── ExecutorRedissonNormal.java │ │ └── resources │ │ └── application.properties ├── pom.xml ├── mvnw.cmd └── mvnw ├── redis-distributed-lock-demo-spring ├── src │ ├── main │ │ ├── resources │ │ │ ├── META-INF │ │ │ │ └── spring-devtools.properties │ │ │ ├── application.properties │ │ │ ├── banner.txt │ │ │ ├── redis.properties │ │ │ ├── application-dev.properties │ │ │ ├── application-test.properties │ │ │ └── application-prod.properties │ │ └── java │ │ │ └── com │ │ │ └── snowalker │ │ │ ├── executor │ │ │ ├── ExecutorA.java │ │ │ ├── ExecutorB.java │ │ │ └── ExecutorRedisson.java │ │ │ └── AlipayGatewayServerBootstrap.java │ └── test │ │ └── java │ │ └── com │ │ └── snowalker │ │ └── AppTest.java └── pom.xml ├── redis-distributed-lock-starter ├── src │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ └── spring.factories │ │ └── java │ │ └── com │ │ └── snowalker │ │ └── lock │ │ └── redisson │ │ ├── config │ │ ├── EnableRedissonLock.java │ │ ├── strategy │ │ │ ├── RedissonConfigStrategy.java │ │ │ ├── RedissonConfigContext.java │ │ │ ├── StandaloneRedissonConfigStrategyImpl.java │ │ │ ├── ClusterRedissonConfigStrategyImpl.java │ │ │ ├── SentinelRedissonConfigStrategyImpl.java │ │ │ └── MasterslaveRedissonConfigStrategyImpl.java │ │ ├── RedissonProperties.java │ │ └── RedissonAutoConfiguration.java │ │ ├── annotation │ │ ├── DistributedLock.java │ │ └── DistributedLockHandler.java │ │ ├── constant │ │ ├── GlobalConstant.java │ │ └── RedisConnectionType.java │ │ ├── RedissonLock.java │ │ └── RedissonManager.java ├── .gitignore ├── readme.md ├── conf │ └── application.properties ├── pom.xml ├── mvnw.cmd └── mvnw ├── .gitignore ├── redis-distributed-lock-core ├── src │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── snowalker │ │ │ └── AppTest.java │ └── main │ │ └── java │ │ └── com │ │ └── snowalker │ │ ├── annotation │ │ └── RedisLock.java │ │ ├── lock │ │ ├── DistributedLock.java │ │ ├── redisson │ │ │ ├── RedissonLock.java │ │ │ └── RedissonManager.java │ │ └── RedisDistributedLock.java │ │ ├── util │ │ └── PropertiesUtil.java │ │ ├── handler │ │ └── RedisLockHandler.java │ │ └── config │ │ ├── RedisPoolUtil.java │ │ └── RedisPool.java ├── conf │ └── redis.properties ├── readme.md └── pom.xml ├── pom.xml ├── README.md └── LICENSE /redis-distributed-lock-starter-demo/readme.md: -------------------------------------------------------------------------------- 1 | # 开分支到dev -------------------------------------------------------------------------------- /redis-distributed-lock-demo-spring/src/main/resources/META-INF/spring-devtools.properties: -------------------------------------------------------------------------------- 1 | restart.include.companycommonlibs=tk/mybatis.* -------------------------------------------------------------------------------- /redis-distributed-lock-demo-spring/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.profiles.active=dev 2 | spring.application.name=alipay-gateway-server 3 | spring.application.version=1.0.0 4 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.snowalker.lock.redisson.config.RedissonAutoConfiguration -------------------------------------------------------------------------------- /redis-distributed-lock-starter/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | .idea 22 | /target/* 23 | *.iml 24 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | hs_err_pid* 26 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter-demo/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /redis-distributed-lock-core/src/test/java/com/snowalker/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.snowalker; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import org.junit.Test; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | { 12 | /** 13 | * Rigorous Test :-) 14 | */ 15 | @Test 16 | public void shouldAnswerWithTrue() 17 | { 18 | assertTrue( true ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /redis-distributed-lock-demo-spring/src/test/java/com/snowalker/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.snowalker; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import org.junit.Test; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | { 12 | /** 13 | * Rigorous Test :-) 14 | */ 15 | @Test 16 | public void shouldAnswerWithTrue() 17 | { 18 | assertTrue( true ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /redis-distributed-lock-core/src/main/java/com/snowalker/annotation/RedisLock.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author snowalker 7 | * @date 2018-7-9 8 | * @desc redisLock自定义注解 9 | */ 10 | @Documented 11 | @Inherited 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target({ElementType.TYPE, ElementType.METHOD}) 14 | public @interface RedisLock { 15 | 16 | String value() default "redis-lock"; 17 | } 18 | -------------------------------------------------------------------------------- /redis-distributed-lock-core/src/main/java/com/snowalker/lock/DistributedLock.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock; 2 | 3 | /** 4 | * @author snowalker 5 | * @date 2018-7-9 6 | * @desc Redis分布式锁接口声明 7 | */ 8 | public interface DistributedLock { 9 | 10 | /** 11 | * 加锁 12 | * @param lockName 13 | * @return 14 | */ 15 | boolean lock(String lockName); 16 | 17 | /** 18 | * 解锁 19 | * @param lockName 20 | */ 21 | boolean release(String lockName); 22 | } 23 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter-demo/src/test/java/com/snowalker/RedisDistributedLockStarterDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.snowalker; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class RedisDistributedLockStarterDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /redis-distributed-lock-demo-spring/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | 2 | .o .ooooo. ooooooooo. .o. oooooo oooo 3 | o888 888' `Y88. `888 `Y88. .888. `888. .8' 4 | 888 888 888 888 .d88' .8"888. `888. .8' 5 | 888 `Vbood888 888ooo88P' .8' `888. `888.8' 6 | 888 888' 888 .88ooo8888. `888' 7 | 888 .88P' 888 .8' `888. 888 8 | o888o .oP' o888o o88o o8888o o888o 9 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/src/main/java/com/snowalker/lock/redisson/config/EnableRedissonLock.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock.redisson.config; 2 | 3 | import org.springframework.context.annotation.Import; 4 | 5 | import java.lang.annotation.*; 6 | 7 | /** 8 | * @author snowalker 9 | * @date 2018/7/10 10 | * @desc 开启Redisson注解支持 11 | */ 12 | @Inherited 13 | @Documented 14 | @Target(ElementType.TYPE) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Import(RedissonAutoConfiguration.class) 17 | public @interface EnableRedissonLock { 18 | } 19 | -------------------------------------------------------------------------------- /redis-distributed-lock-core/conf/redis.properties: -------------------------------------------------------------------------------- 1 | #最大连接数 2 | redis.max.total=20 3 | #最大空闲连接数,在jedispool中最大的idle状态(空闲的)的jedis实例的个数 4 | redis.max.idle=20 5 | #最小空闲连接数,在jedispool中最小的idle状态(空闲的)的jedis实例的个数 6 | redis.min.idle=10 7 | #在取连接时测试连接的可用性,在borrow一个jedis实例的时候,是否要进行验证操作,如果赋值true。则得到的jedis实例肯定是可以用的 8 | redis.test.borrow=true 9 | #再还连接时不测试连接的可用性,
在return一个jedis实例的时候,是否要进行验证操作,如果赋值true。则放回jedispool的jedis实例肯定是可以用的。 10 | redis.test.return=true 11 | #服务端ip 12 | redis.ip=172.30.66.80 13 | #服务端port 14 | redis.port=6379 15 | #redis连接超时时间 16 | redis.server.timeout=3000 17 | #锁超时时间 18 | redis.lock.timeout=5000 -------------------------------------------------------------------------------- /redis-distributed-lock-demo-spring/src/main/resources/redis.properties: -------------------------------------------------------------------------------- 1 | #最大连接数 2 | redis.max.total=20 3 | #最大空闲连接数,在jedispool中最大的idle状态(空闲的)的jedis实例的个数 4 | redis.max.idle=20 5 | #最小空闲连接数,在jedispool中最小的idle状态(空闲的)的jedis实例的个数 6 | redis.min.idle=10 7 | #在取连接时测试连接的可用性,在borrow一个jedis实例的时候,是否要进行验证操作,如果赋值true。则得到的jedis实例肯定是可以用的 8 | redis.test.borrow=true 9 | #再还连接时不测试连接的可用性,
在return一个jedis实例的时候,是否要进行验证操作,如果赋值true。则放回jedispool的jedis实例肯定是可以用的。 10 | redis.test.return=true 11 | #服务端ip 12 | redis.ip=192.168.1.108 13 | #服务端port 14 | redis.port=6379 15 | #redis连接超时时间 16 | redis.server.timeout=3000 17 | #锁超时时间 毫秒 18 | redis.lock.timeout=50000 -------------------------------------------------------------------------------- /redis-distributed-lock-starter/src/main/java/com/snowalker/lock/redisson/annotation/DistributedLock.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock.redisson.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author snowalker 7 | * @date 2018/7/10 8 | * @desc Redisson分布式锁注解 9 | */ 10 | @Documented 11 | @Inherited 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target({ElementType.TYPE, ElementType.METHOD}) 14 | public @interface DistributedLock { 15 | 16 | /**分布式锁名称*/ 17 | String value() default "distributed-lock-redisson"; 18 | /**锁超时时间,默认十秒*/ 19 | int expireSeconds() default 10; 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/src/main/java/com/snowalker/lock/redisson/config/strategy/RedissonConfigStrategy.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock.redisson.config.strategy; 2 | 3 | import com.snowalker.lock.redisson.config.RedissonProperties; 4 | import org.redisson.config.Config; 5 | 6 | /** 7 | * @author snowalker 8 | * @date 2018/7/12 9 | * @desc Redisson配置构建接口 10 | */ 11 | public interface RedissonConfigStrategy { 12 | 13 | /** 14 | * 根据不同的Redis配置策略创建对应的Config 15 | * @param redissonProperties 16 | * @return Config 17 | */ 18 | Config createRedissonConfig(RedissonProperties redissonProperties); 19 | } 20 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter-demo/src/main/java/com/snowalker/RedisDistributedLockStarterDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.snowalker; 2 | 3 | import com.snowalker.lock.redisson.config.EnableRedissonLock; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.scheduling.annotation.EnableScheduling; 7 | 8 | @EnableRedissonLock 9 | @EnableScheduling 10 | @SpringBootApplication 11 | public class RedisDistributedLockStarterDemoApplication { 12 | 13 | public static void main(String[] args) throws Exception { 14 | SpringApplication.run(RedisDistributedLockStarterDemoApplication.class, args); 15 | } 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | 7 | com.snowalker 8 | redis-distributed-lock 9 | 1.0.0 10 | 11 | redis-distributed-lock-core 12 | redis-distributed-lock-demo-spring 13 | redis-distributed-lock-starter 14 | redis-distributed-lock-starter-demo 15 | 16 | pom 17 | 18 | redis-distributed-lock 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/src/main/java/com/snowalker/lock/redisson/constant/GlobalConstant.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock.redisson.constant; 2 | 3 | /** 4 | * @author snowalker 5 | * @date 2018/7/12 6 | * @desc 全局常量枚举 7 | */ 8 | public enum GlobalConstant { 9 | 10 | REDIS_CONNECTION_PREFIX("redis://", "Redis地址配置前缀"); 11 | 12 | private final String constant_value; 13 | private final String constant_desc; 14 | 15 | private GlobalConstant(String constant_value, String constant_desc) { 16 | this.constant_value = constant_value; 17 | this.constant_desc = constant_desc; 18 | } 19 | 20 | public String getConstant_value() { 21 | return constant_value; 22 | } 23 | 24 | public String getConstant_desc() { 25 | return constant_desc; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /redis-distributed-lock-demo-spring/src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # 3 | # 启动端口号 4 | # 5 | ########################################################################## 6 | server.port=8081 7 | # app-name (need to modify) 8 | spring.application.name=redis-distributed-lock-demo-spring 9 | ######################################################################## 10 | # 11 | # 日志配置 12 | # 13 | ######################################################################### 14 | logging.pattern.console=%-12(%d{yyyy-MM-dd HH:mm:ss.SSS}) |-%-5level [%thread] %c [%L] -| %msg%n 15 | logging.pattern.file=%-12(%d{yyyy-MM-dd HH:mm:ss.SSS}) |-%-5level [%thread] %c [%L] -| %msg%n 16 | logging.file=d:/log/redis-distributed-lock-demo-spring/console.log 17 | logging.level.com.gaoyang=INFO 18 | 19 | redis.lock.cron=0/3 * * * * ? 20 | -------------------------------------------------------------------------------- /redis-distributed-lock-demo-spring/src/main/java/com/snowalker/executor/ExecutorA.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.executor; 2 | 3 | import com.snowalker.annotation.RedisLock; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.scheduling.annotation.Scheduled; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * @author snowalker 11 | * @date 2018-7-9 12 | * @desc 分布式锁注解支持 13 | */ 14 | @Component 15 | public class ExecutorA { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(ExecutorA.class); 18 | 19 | @Scheduled(cron = "${redis.lock.cron}") 20 | @RedisLock(value = "executor") 21 | public void execute() throws InterruptedException { 22 | LOGGER.info("[ExecutorA]--执行定时任务开始,休眠三秒"); 23 | Thread.sleep(3000); 24 | System.out.println("===================================================="); 25 | LOGGER.info("[ExecutorA]--执行定时任务结束,休眠三秒"); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/src/main/java/com/snowalker/lock/redisson/config/strategy/RedissonConfigContext.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock.redisson.config.strategy; 2 | 3 | import com.snowalker.lock.redisson.config.RedissonProperties; 4 | import org.redisson.config.Config; 5 | 6 | /** 7 | * @author snowalker 8 | * @date 2018/7/12 9 | * @desc Redisson配置上下文,产出真正的Redisson的Config 10 | */ 11 | public class RedissonConfigContext { 12 | 13 | private RedissonConfigStrategy redissonConfigStrategy = null; 14 | 15 | public RedissonConfigContext(RedissonConfigStrategy _redissonConfigStrategy) { 16 | this.redissonConfigStrategy = _redissonConfigStrategy; 17 | } 18 | 19 | /** 20 | * 上下文根据构造中传入的具体策略产出真实的Redisson的Config 21 | * @param redissonProperties 22 | * @return 23 | */ 24 | public Config createRedissonConfig(RedissonProperties redissonProperties) { 25 | return this.redissonConfigStrategy.createRedissonConfig(redissonProperties); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/src/main/java/com/snowalker/lock/redisson/constant/RedisConnectionType.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock.redisson.constant; 2 | 3 | /** 4 | * @author snowalker 5 | * @date 2018/7/11 6 | * @desc Redis连接方式 7 | * 包含:standalone-单节点部署方式 8 | * sentinel-哨兵部署方式 9 | * cluster-集群方式 10 | * masterslave-主从部署方式 11 | */ 12 | public enum RedisConnectionType { 13 | 14 | STANDALONE("standalone", "单节点部署方式"), 15 | SENTINEL("sentinel", "哨兵部署方式"), 16 | CLUSTER("cluster", "集群方式"), 17 | MASTERSLAVE("masterslave", "主从部署方式"); 18 | 19 | private final String connection_type; 20 | private final String connection_desc; 21 | 22 | private RedisConnectionType(String connection_type, String connection_desc) { 23 | this.connection_type = connection_type; 24 | this.connection_desc = connection_desc; 25 | } 26 | 27 | public String getConnection_type() { 28 | return connection_type; 29 | } 30 | 31 | public String getConnection_desc() { 32 | return connection_desc; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter-demo/src/main/java/com/snowalker/executor/ExecutorRedissonAnnotation.java: -------------------------------------------------------------------------------- 1 | //package com.snowalker.executor; 2 | // 3 | //import com.snowalker.lock.redisson.annotation.DistributedLock; 4 | //import org.slf4j.Logger; 5 | //import org.slf4j.LoggerFactory; 6 | //import org.springframework.scheduling.annotation.Scheduled; 7 | //import org.springframework.stereotype.Component; 8 | // 9 | ///** 10 | // * @author wuwl@19pay.com.cn 11 | // * @date 2018-7-9 12 | // * @desc 纯java调用 13 | // */ 14 | //@Component 15 | //public class ExecutorRedissonAnnotation { 16 | // 17 | // private static final Logger LOGGER = LoggerFactory.getLogger(ExecutorRedissonAnnotation.class); 18 | // 19 | // @Scheduled(cron = "${redis.lock.cron}") 20 | // @DistributedLock(value = "redis-lock", expireSeconds = 11) 21 | // public void execute() throws InterruptedException { 22 | // LOGGER.info("[ExecutorRedisson]--执行定时任务开始,休眠三秒"); 23 | // Thread.sleep(3000); 24 | // System.out.println("=======================业务逻辑============================="); 25 | // LOGGER.info("[ExecutorRedisson]--执行定时任务结束,休眠三秒"); 26 | // } 27 | //} 28 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # 3 | # 基础配置 4 | # 5 | ########################################################################## 6 | server.port=8889 7 | # app-name (need to modify) 8 | spring.application.name=redis-distributed-lock-demo-spring 9 | ######################################################################## 10 | # 11 | # 日志配置 12 | # 13 | ######################################################################### 14 | logging.pattern.console=%-12(%d{yyyy-MM-dd HH:mm:ss.SSS}) |-%-5level [%thread] %c [%L] -| %msg%n 15 | logging.pattern.file=%-12(%d{yyyy-MM-dd HH:mm:ss.SSS}) |-%-5level [%thread] %c [%L] -| %msg%n 16 | logging.file=d:/log/redis-distributed-lock-demo-spring/console.log 17 | logging.level.com.gaoyang=DEBUG 18 | 19 | redis.lock.cron=0/5 * * * * ? 20 | ######################################################################## 21 | # 22 | # redisson配置 23 | # 24 | ######################################################################### 25 | redisson.lock.server.address=127.0.0.1:6379 26 | redisson.lock.server.password= 27 | redisson.lock.server.database=1 28 | redisson.lock.server.type=standalone -------------------------------------------------------------------------------- /redis-distributed-lock-demo-spring/src/main/java/com/snowalker/executor/ExecutorB.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.executor; 2 | 3 | import com.snowalker.annotation.RedisLock; 4 | import com.snowalker.lock.RedisDistributedLock; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.scheduling.annotation.Scheduled; 8 | import org.springframework.stereotype.Component; 9 | 10 | /** 11 | * @author snowalker 12 | * @date 2018-7-9 13 | * @desc 纯java调用 14 | */ 15 | @Component 16 | public class ExecutorB { 17 | 18 | private static final Logger LOGGER = LoggerFactory.getLogger(ExecutorB.class); 19 | 20 | @Scheduled(cron = "${redis.lock.cron}") 21 | public void execute() throws InterruptedException { 22 | RedisDistributedLock lock = RedisDistributedLock.getInstance(); 23 | if (lock.lock("AAAAAAA")) { 24 | LOGGER.info("[ExecutorB]--执行定时任务开始,休眠三秒"); 25 | Thread.sleep(3000); 26 | System.out.println("=======================业务逻辑============================="); 27 | LOGGER.info("[ExecutorB]--执行定时任务结束,休眠三秒"); 28 | lock.release("AAAAAAA"); 29 | } else { 30 | LOGGER.info("【ExecutorB】获取锁失败"); 31 | } 32 | 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/readme.md: -------------------------------------------------------------------------------- 1 | # 开发一个spring-boot-starter的步骤 2 | 1. 新建一个maven项目 3 | 2. 需要一个配置类RedisAutoConfiguration,在配置类里面装配好需要提供出去的类 4 | 3. 使用@Enable配合@Import导入需要装配的类 或者 META-INF/spring.factories中配置 5 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.snowalker.demo.redis.RedisAutoConfiguration 6 | 7 | ## redis分布式锁starter--基于Redisson 8 | ### 配置文件 9 | redisson.lock.server.address=127.0.0.1:6379 10 | redisson.lock.server.type=standalone 11 | ### 更新记录 12 | 1. 改变配置方式,增加对不同Redis连接方式的支持 13 |
去除以下方法RedissonManager(String redisIp, String redisPort) 14 | 15 | public RedissonManager (String redisIp, String redisPort) { 16 | try { 17 | String redisAddr = new StringBuilder("redis://") 18 | .append(redisIp).append(":").append(redisPort) 19 | .toString(); 20 | config.useSingleServer().setAddress(redisAddr); 21 | redisson = (Redisson) Redisson.create(config); 22 | LOGGER.info("初始化Redisson结束,redisAddress:" + redisAddr); 23 | } catch (Exception e) { 24 | LOGGER.error("Redisson init error", e); 25 | e.printStackTrace(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /redis-distributed-lock-core/readme.md: -------------------------------------------------------------------------------- 1 | # redis分布式锁 2 | ## 1. 使用配置 3 | 4 | >配置文件为redis.properties,需要放在类路径下,编码格式UTF-8 5 | 6 | ### 1.2 配置项目 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
参数名称参数解释
redis.max.total最大连接数
redis.max.idle最大空闲连接数,在jedispool中最大的idle状态(空闲的)的jedis实例的个数
redis.min.idle最小空闲连接数,在jedispool中最小的idle状态(空闲的)的jedis实例的个数
redis.test.borrow在取连接时测试连接的可用性,在borrow一个jedis实例的时候,
是否要进行验证操作,如果赋值true。则得到的jedis实例肯定是可以用的
redis.test.return再还连接时不测试连接的可用性,
在return一个jedis实例的时候,是否要进行验证操作,如果赋值true。则放回jedispool的jedis实例肯定是可以用的。
redis.ipredis服务端ip
redis.portredis服务端port
redis.server.timeoutredis连接超时时间
redis.lock.timeout锁超时时间
-------------------------------------------------------------------------------- /redis-distributed-lock-starter-demo/src/main/java/com/snowalker/executor/ExecutorRedissonNormal.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.executor; 2 | 3 | import com.snowalker.lock.redisson.RedissonLock; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.scheduling.annotation.Scheduled; 8 | import org.springframework.stereotype.Component; 9 | 10 | /** 11 | * @author wuwl@19pay.com.cn 12 | * @date 2018-7-9 13 | * @desc 纯java调用 14 | */ 15 | @Component 16 | public class ExecutorRedissonNormal { 17 | 18 | private static final Logger LOGGER = LoggerFactory.getLogger(ExecutorRedissonNormal.class); 19 | 20 | @Autowired 21 | RedissonLock redissonLock; 22 | 23 | @Scheduled(cron = "${redis.lock.cron}") 24 | public void execute() throws InterruptedException { 25 | if (redissonLock.lock("redisson", 10)) { 26 | LOGGER.info("[ExecutorRedisson]--执行定时任务开始,休眠三秒"); 27 | Thread.sleep(3000); 28 | System.out.println("=======================业务逻辑============================="); 29 | LOGGER.info("[ExecutorRedisson]--执行定时任务结束,休眠三秒"); 30 | redissonLock.release("redisson"); 31 | } else { 32 | LOGGER.info("[ExecutorRedisson]获取锁失败"); 33 | } 34 | 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /redis-distributed-lock-demo-spring/src/main/java/com/snowalker/executor/ExecutorRedisson.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.executor; 2 | 3 | //import com.snowalker.annotation.RedisLock; 4 | //import com.snowalker.lock.RedisDistributedLock; 5 | import com.snowalker.lock.redisson.RedissonLock; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.scheduling.annotation.Scheduled; 10 | import org.springframework.stereotype.Component; 11 | 12 | /** 13 | * @author snowalker 14 | * @date 2018-7-9 15 | * @desc Redisson锁 16 | */ 17 | @Component 18 | public class ExecutorRedisson { 19 | 20 | private static final Logger LOGGER = LoggerFactory.getLogger(ExecutorRedisson.class); 21 | 22 | @Autowired 23 | RedissonLock redissonLock; 24 | 25 | 26 | @Scheduled(cron = "${redis.lock.cron}") 27 | public void execute() throws InterruptedException { 28 | if (redissonLock.lock("snowalker", 5)) { 29 | LOGGER.info("[ExecutorRedisson]--执行定时任务开始,休眠三秒"); 30 | Thread.sleep(3000); 31 | System.out.println("=======================业务逻辑============================="); 32 | LOGGER.info("[ExecutorRedisson]--执行定时任务结束,休眠三秒"); 33 | redissonLock.release("snowalker"); 34 | } else { 35 | LOGGER.info("[ExecutorRedisson]获取锁失败"); 36 | } 37 | 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /redis-distributed-lock-core/src/main/java/com/snowalker/util/PropertiesUtil.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.util; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStreamReader; 5 | import java.util.Properties; 6 | 7 | import org.apache.commons.lang3.StringUtils; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | /** 12 | * @author snowalker 13 | * @date 2017-9-21 14 | * @describe 配置文件读取 15 | */ 16 | public class PropertiesUtil { 17 | 18 | private static final Logger log = LoggerFactory.getLogger(PropertiesUtil.class); 19 | 20 | private static Properties props; 21 | 22 | static { 23 | String fileName = "redis.properties"; 24 | props = new Properties(); 25 | try { 26 | props.load(new InputStreamReader(PropertiesUtil.class.getClassLoader().getResourceAsStream(fileName),"UTF-8")); 27 | } catch (IOException e) { 28 | log.error("配置文件读取异常",e); 29 | } 30 | } 31 | 32 | public static String getProperty(String key){ 33 | String value = props.getProperty(key.trim()); 34 | if(StringUtils.isBlank(value)){ 35 | return null; 36 | } 37 | return value.trim(); 38 | } 39 | 40 | public static String getProperty(String key,String defaultValue){ 41 | 42 | String value = props.getProperty(key.trim()); 43 | if(StringUtils.isBlank(value)){ 44 | value = defaultValue; 45 | } 46 | return value.trim(); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/src/main/java/com/snowalker/lock/redisson/config/RedissonProperties.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock.redisson.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | /** 6 | * @author snowalker 7 | * @date 2018/7/10 8 | * @desc Redisson配置映射类 9 | */ 10 | @ConfigurationProperties(prefix = "redisson.lock.server") 11 | public class RedissonProperties { 12 | 13 | /**redis主机地址,ip:port,有多个用半角逗号分隔*/ 14 | private String address; 15 | /**连接类型,支持standalone-单机节点,sentinel-哨兵,cluster-集群,masterslave-主从*/ 16 | private String type; 17 | /**redis连接密码*/ 18 | private String password; 19 | /**选取那个数据库*/ 20 | private int database; 21 | 22 | public String getPassword() { 23 | return password; 24 | } 25 | 26 | public RedissonProperties setPassword(String password) { 27 | this.password = password; 28 | return this; 29 | } 30 | 31 | public int getDatabase() { 32 | return database; 33 | } 34 | 35 | public RedissonProperties setDatabase(int database) { 36 | this.database = database; 37 | return this; 38 | } 39 | 40 | public String getAddress() { 41 | return address; 42 | } 43 | 44 | public void setAddress(String address) { 45 | this.address = address; 46 | } 47 | 48 | public String getType() { 49 | return type; 50 | } 51 | 52 | public void setType(String type) { 53 | this.type = type; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /redis-distributed-lock-core/src/main/java/com/snowalker/lock/redisson/RedissonLock.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock.redisson; 2 | 3 | import org.redisson.api.RLock; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.concurrent.TimeUnit; 10 | 11 | /** 12 | * @author snowalker 13 | * @date 2018/7/10 14 | * @desc 分布式基于Redisson 15 | */ 16 | @Component 17 | public class RedissonLock { 18 | 19 | private static final Logger LOGGER = LoggerFactory.getLogger(RedissonLock.class); 20 | 21 | @Autowired 22 | RedissonManager redissonManager; 23 | 24 | /** 25 | * 加锁操作 26 | * @return 27 | */ 28 | public boolean lock(String lockName, long expireSeconds) { 29 | RLock rLock = redissonManager.getRedisson().getLock(lockName); 30 | boolean getLock = false; 31 | try { 32 | getLock = rLock.tryLock(0, expireSeconds, TimeUnit.SECONDS); 33 | if (getLock) { 34 | LOGGER.info("获取Redisson分布式锁[成功],lockName={}", lockName); 35 | } else { 36 | LOGGER.info("获取Redisson分布式锁[失败],lockName={}", lockName); 37 | } 38 | } catch (InterruptedException e) { 39 | LOGGER.error("获取Redisson分布式锁[异常],lockName=" + lockName, e); 40 | e.printStackTrace(); 41 | } 42 | return getLock; 43 | } 44 | 45 | /** 46 | * 解锁 47 | * @param lockName 48 | */ 49 | public void release(String lockName) { 50 | redissonManager.getRedisson().getLock(lockName).unlock(); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /redis-distributed-lock-core/src/main/java/com/snowalker/handler/RedisLockHandler.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.handler; 2 | 3 | import com.snowalker.annotation.RedisLock; 4 | import com.snowalker.lock.RedisDistributedLock; 5 | import org.aspectj.lang.ProceedingJoinPoint; 6 | import org.aspectj.lang.annotation.Around; 7 | import org.aspectj.lang.annotation.Aspect; 8 | import org.aspectj.lang.annotation.Pointcut; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.stereotype.Component; 12 | 13 | /** 14 | * @author snowalker 15 | * @date 2018-7-9 16 | * @desc Redis分布式锁注解解析器 17 | */ 18 | @Aspect 19 | @Component 20 | public class RedisLockHandler { 21 | 22 | private static final Logger LOGGER = LoggerFactory.getLogger(RedisLockHandler.class); 23 | 24 | @Pointcut("@annotation(com.snowalker.annotation.RedisLock)") 25 | public void redisLock() {} 26 | 27 | @Around("@annotation(redisLock)") 28 | public void around(ProceedingJoinPoint joinPoint, RedisLock redisLock) { 29 | LOGGER.info("[开始]执行RedisLock环绕通知,获取Redis分布式锁开始"); 30 | String lockName = redisLock.value(); 31 | RedisDistributedLock redisDistributedLock = RedisDistributedLock.getInstance(); 32 | if (redisDistributedLock.lock(lockName)) { 33 | try { 34 | LOGGER.info("获取Redis分布式锁[成功]"); 35 | joinPoint.proceed(); 36 | } catch (Throwable throwable) { 37 | throwable.printStackTrace(); 38 | } 39 | LOGGER.info("释放Redis分布式锁[成功]"); 40 | redisDistributedLock.release(lockName); 41 | } else { 42 | LOGGER.error("获取Redis分布式锁[失败]"); 43 | } 44 | LOGGER.error("[结束]执行RedisLock环绕通知"); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /redis-distributed-lock-demo-spring/src/main/java/com/snowalker/AlipayGatewayServerBootstrap.java: -------------------------------------------------------------------------------- 1 | package com.snowalker; 2 | 3 | import org.apache.catalina.connector.Connector; 4 | import org.apache.coyote.http11.Http11NioProtocol; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.boot.SpringApplication; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; 10 | import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer; 11 | import org.springframework.scheduling.annotation.EnableScheduling; 12 | 13 | @EnableScheduling 14 | @SpringBootApplication(exclude={DataSourceAutoConfiguration.class}) 15 | public class AlipayGatewayServerBootstrap { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(AlipayGatewayServerBootstrap.class); 18 | 19 | public static void main(String[] args) { 20 | SpringApplication.run(AlipayGatewayServerBootstrap.class, args); 21 | LOGGER.info("redis-distributed-lock-demo-spring启动完成......"); 22 | } 23 | 24 | /** 25 | * @author snowalker 26 | * @date 2017-3-17 27 | * @describe 优化tomcat线程数目 28 | */ 29 | class MyTomcatConnectorCustomizer implements TomcatConnectorCustomizer { 30 | @Override 31 | public void customize(Connector connector) { 32 | Http11NioProtocol protocol = (Http11NioProtocol) connector 33 | .getProtocolHandler(); 34 | // 设置最大连接数 35 | protocol.setMaxConnections(2000); 36 | // 设置最大线程数 37 | protocol.setMaxThreads(2000); 38 | protocol.setConnectionTimeout(30000); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/src/main/java/com/snowalker/lock/redisson/config/strategy/StandaloneRedissonConfigStrategyImpl.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock.redisson.config.strategy; 2 | 3 | import com.snowalker.lock.redisson.config.RedissonProperties; 4 | import com.snowalker.lock.redisson.constant.GlobalConstant; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.redisson.config.Config; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | /** 11 | * @author snowalker 12 | * @date 2018/7/12 13 | * @desc 单机方式Redisson配置 14 | */ 15 | public class StandaloneRedissonConfigStrategyImpl implements RedissonConfigStrategy { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(StandaloneRedissonConfigStrategyImpl.class); 18 | 19 | @Override 20 | public Config createRedissonConfig(RedissonProperties redissonProperties) { 21 | Config config = new Config(); 22 | try { 23 | String address = redissonProperties.getAddress(); 24 | String password = redissonProperties.getPassword(); 25 | int database = redissonProperties.getDatabase(); 26 | String redisAddr = GlobalConstant.REDIS_CONNECTION_PREFIX.getConstant_value() + address; 27 | config.useSingleServer().setAddress(redisAddr); 28 | config.useSingleServer().setDatabase(database); 29 | if (StringUtils.isNotBlank(password)) { 30 | config.useSingleServer().setPassword(password); 31 | } 32 | LOGGER.info("初始化[standalone]方式Config,redisAddress:" + address); 33 | } catch (Exception e) { 34 | LOGGER.error("standalone Redisson init error", e); 35 | e.printStackTrace(); 36 | } 37 | return config; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /redis-distributed-lock-core/src/main/java/com/snowalker/lock/redisson/RedissonManager.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock.redisson; 2 | 3 | import com.snowalker.util.PropertiesUtil; 4 | import org.redisson.Redisson; 5 | import org.redisson.config.Config; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.stereotype.Component; 9 | 10 | import javax.annotation.PostConstruct; 11 | 12 | /** 13 | * @author snowalker 14 | * @date 2018/7/10 15 | * @desc 16 | */ 17 | @Component 18 | public class RedissonManager { 19 | 20 | private static final Logger LOGGER = LoggerFactory.getLogger(Redisson.class); 21 | 22 | private Config config = new Config(); 23 | 24 | private Redisson redisson = null; 25 | 26 | private static String redisIp = 27 | PropertiesUtil.getProperty("redis.ip", "127.0.0.1"); 28 | 29 | private static String redisPort = 30 | PropertiesUtil.getProperty("redis.port", "6379"); 31 | 32 | @PostConstruct 33 | private void init() { 34 | try { 35 | config.useSingleServer().setAddress( 36 | new StringBuilder("redis://") 37 | .append(redisIp).append(":").append(redisPort).toString()); 38 | redisson = (Redisson) Redisson.create(config); 39 | LOGGER.info("初始化Redisson结束"); 40 | } catch (Exception e) { 41 | LOGGER.error("Redisson init error", e); 42 | e.printStackTrace(); 43 | } 44 | } 45 | 46 | public Redisson getRedisson() { 47 | return redisson; 48 | } 49 | 50 | 51 | public static void main(String[] args) { 52 | Config config = new Config(); 53 | config.useSingleServer().setAddress("redis://127.0.0.1:6379"); 54 | Redisson redisson = (Redisson) Redisson.create(config); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/src/main/java/com/snowalker/lock/redisson/RedissonLock.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock.redisson; 2 | 3 | import org.redisson.api.RLock; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import java.util.concurrent.TimeUnit; 8 | 9 | /** 10 | * @author snowalker 11 | * @date 2018/7/10 12 | * @desc 分布式锁实现基于Redisson 13 | */ 14 | public class RedissonLock { 15 | 16 | private static final Logger LOGGER = LoggerFactory.getLogger(RedissonLock.class); 17 | 18 | RedissonManager redissonManager; 19 | 20 | public RedissonLock(RedissonManager redissonManager) { 21 | this.redissonManager = redissonManager; 22 | } 23 | 24 | public RedissonLock() {} 25 | /** 26 | * 加锁操作 27 | * @return 28 | */ 29 | public boolean lock(String lockName, long expireSeconds) { 30 | RLock rLock = redissonManager.getRedisson().getLock(lockName); 31 | boolean getLock = false; 32 | try { 33 | getLock = rLock.tryLock(0, expireSeconds, TimeUnit.SECONDS); 34 | if (getLock) { 35 | LOGGER.info("获取Redisson分布式锁[成功],lockName={}", lockName); 36 | } else { 37 | LOGGER.info("获取Redisson分布式锁[失败],lockName={}", lockName); 38 | } 39 | } catch (InterruptedException e) { 40 | LOGGER.error("获取Redisson分布式锁[异常],lockName=" + lockName, e); 41 | e.printStackTrace(); 42 | return false; 43 | } 44 | return getLock; 45 | } 46 | 47 | /** 48 | * 解锁 49 | * @param lockName 50 | */ 51 | public void release(String lockName) { 52 | redissonManager.getRedisson().getLock(lockName).unlock(); 53 | } 54 | 55 | public RedissonManager getRedissonManager() { 56 | return redissonManager; 57 | } 58 | 59 | public void setRedissonManager(RedissonManager redissonManager) { 60 | this.redissonManager = redissonManager; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/src/main/java/com/snowalker/lock/redisson/config/RedissonAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock.redisson.config; 2 | 3 | import com.snowalker.lock.redisson.RedissonLock; 4 | import com.snowalker.lock.redisson.RedissonManager; 5 | import org.redisson.Redisson; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 10 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.context.annotation.Configuration; 13 | import org.springframework.core.annotation.Order; 14 | 15 | /** 16 | * @author snowalker 17 | * @date 2018/7/10 18 | * @desc Redisson自动化配置 19 | */ 20 | @Configuration 21 | @ConditionalOnClass(Redisson.class) 22 | @EnableConfigurationProperties(RedissonProperties.class) 23 | public class RedissonAutoConfiguration { 24 | 25 | private static final Logger LOGGER = LoggerFactory.getLogger(RedissonAutoConfiguration.class); 26 | 27 | @Bean 28 | @ConditionalOnMissingBean 29 | @Order(value = 2) 30 | public RedissonLock redissonLock(RedissonManager redissonManager) { 31 | RedissonLock redissonLock = new RedissonLock(); 32 | redissonLock.setRedissonManager(redissonManager); 33 | LOGGER.info("[RedissonLock]组装完毕"); 34 | return redissonLock; 35 | } 36 | 37 | @Bean 38 | @ConditionalOnMissingBean 39 | @Order(value = 1) 40 | public RedissonManager redissonManager(RedissonProperties redissonProperties) { 41 | RedissonManager redissonManager = 42 | new RedissonManager(redissonProperties); 43 | LOGGER.info("[RedissonManager]组装完毕,当前连接方式:" + redissonProperties.getType() + 44 | ",连接地址:" + redissonProperties.getAddress()); 45 | return redissonManager; 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/src/main/java/com/snowalker/lock/redisson/config/strategy/ClusterRedissonConfigStrategyImpl.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock.redisson.config.strategy; 2 | 3 | import com.snowalker.lock.redisson.config.RedissonProperties; 4 | import com.snowalker.lock.redisson.constant.GlobalConstant; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.redisson.config.Config; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | /** 11 | * @author snowalker 12 | * @date 2018/7/12 13 | * @desc 集群方式Redisson配置 14 | * 地址格式: 15 | * cluster方式至少6个节点(3主3从,3主做sharding,3从用来保证主宕机后可以高可用) 16 | * 格式为: 127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381,127.0.0.1:6382,127.0.0.1:6383,127.0.0.1:6384 17 | */ 18 | public class ClusterRedissonConfigStrategyImpl implements RedissonConfigStrategy { 19 | 20 | private static final Logger LOGGER = LoggerFactory.getLogger(ClusterRedissonConfigStrategyImpl.class); 21 | 22 | @Override 23 | public Config createRedissonConfig(RedissonProperties redissonProperties) { 24 | Config config = new Config(); 25 | try { 26 | String address = redissonProperties.getAddress(); 27 | String password = redissonProperties.getPassword(); 28 | String[] addrTokens = address.split(","); 29 | /**设置cluster节点的服务IP和端口*/ 30 | for (int i = 0; i < addrTokens.length; i++) { 31 | config.useClusterServers() 32 | .addNodeAddress(GlobalConstant.REDIS_CONNECTION_PREFIX.getConstant_value() + addrTokens[i]); 33 | if (StringUtils.isNotBlank(password)) { 34 | config.useClusterServers().setPassword(password); 35 | } 36 | } 37 | LOGGER.info("初始化[cluster]方式Config,redisAddress:" + address); 38 | } catch (Exception e) { 39 | LOGGER.error("cluster Redisson init error", e); 40 | e.printStackTrace(); 41 | } 42 | return config; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/conf/application.properties: -------------------------------------------------------------------------------- 1 | ######################################################################## 2 | # 3 | # redisson单机配置 4 | # 5 | ######################################################################### 6 | #redisson.lock.server.address=127.0.0.1:6379 7 | #redisson.lock.server.type=standalone 8 | #redisson.lock.server.password= 9 | #redisson.lock.server.database=1 10 | ######################################################################## 11 | # 12 | # redisson哨兵配置 13 | # **redisson.lock.server.address** 格式为: sentinel.conf配置里的sentinel别名, 14 | # sentinel1节点的服务IP和端口,sentinel2节点的服务IP和端口,sentinel3节点的服务IP和端口 15 | # 16 | # 比如sentinel.conf里配置为sentinel monitor my-sentinel-name 127.0.0.1 6379 2,那么这里就配置my-sentinel-name 17 | # 18 | ######################################################################### 19 | #redisson.server.address=my-sentinel-name,127.0.0.1:26379,127.0.0.1:26389,127.0.0.1:26399 20 | #redisson.server.type=sentinel 21 | #redisson.lock.server.password= 22 | #redisson.lock.server.database=1 23 | ######################################################################## 24 | # 25 | # redisson分布式锁配置--集群方式 26 | # cluster方式至少6个节点(3主3从,3主做sharding,3从用来保证主宕机后可以高可用) 27 | # 地址格式为: 127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381,127.0.0.1:6382,127.0.0.1:6383,127.0.0.1:6384 28 | ######################################################################### 29 | #redisson.server.address=127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381,127.0.0.1:6382,127.0.0.1:6383,127.0.0.1:6384 30 | #redisson.server.type=cluster 31 | #redisson.lock.server.password= 32 | ######################################################################## 33 | # 34 | # redisson分布式锁配置--主从 35 | # 地址格式为**主节点,子节点,子节点** 36 | # 代表主节点:127.0.0.1:6379,从节点127.0.0.1:6380,127.0.0.1:6381 37 | 38 | ######################################################################### 39 | #redisson.server.address=127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381 40 | #redisson.server.type=masterslave 41 | #redisson.lock.server.password= 42 | #redisson.lock.server.database=1 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/src/main/java/com/snowalker/lock/redisson/annotation/DistributedLockHandler.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock.redisson.annotation; 2 | 3 | import com.snowalker.lock.redisson.RedissonLock; 4 | import org.aspectj.lang.ProceedingJoinPoint; 5 | import org.aspectj.lang.annotation.Around; 6 | import org.aspectj.lang.annotation.Aspect; 7 | import org.aspectj.lang.annotation.Pointcut; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Component; 12 | 13 | /** 14 | * @author snowalker 15 | * @date 2018/7/10 16 | * @desc Redisson分布式锁注解解析器 17 | */ 18 | @Aspect 19 | @Component 20 | public class DistributedLockHandler { 21 | 22 | private static final Logger LOGGER = LoggerFactory.getLogger(DistributedLockHandler.class); 23 | 24 | @Pointcut("@annotation(com.snowalker.lock.redisson.annotation.DistributedLock)") 25 | public void distributedLock() {} 26 | 27 | @Autowired 28 | RedissonLock redissonLock; 29 | 30 | @Around("@annotation(distributedLock)") 31 | public void around(ProceedingJoinPoint joinPoint, DistributedLock distributedLock) { 32 | LOGGER.info("[开始]执行RedisLock环绕通知,获取Redis分布式锁开始"); 33 | /**获取锁名称*/ 34 | String lockName = distributedLock.value(); 35 | /**获取超时时间,默认十秒*/ 36 | int expireSeconds = distributedLock.expireSeconds(); 37 | if (redissonLock.lock(lockName, expireSeconds)) { 38 | try { 39 | LOGGER.info("获取Redis分布式锁[成功],加锁完成,开始执行业务逻辑..."); 40 | joinPoint.proceed(); 41 | } catch (Throwable throwable) { 42 | LOGGER.error("获取Redis分布式锁[异常],加锁失败", throwable); 43 | throwable.printStackTrace(); 44 | } finally { 45 | redissonLock.release(lockName); 46 | } 47 | LOGGER.info("释放Redis分布式锁[成功],解锁完成,结束业务逻辑..."); 48 | } else { 49 | LOGGER.error("获取Redis分布式锁[失败]"); 50 | } 51 | LOGGER.info("[结束]执行RedisLock环绕通知"); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/src/main/java/com/snowalker/lock/redisson/config/strategy/SentinelRedissonConfigStrategyImpl.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock.redisson.config.strategy; 2 | 3 | import com.snowalker.lock.redisson.config.RedissonProperties; 4 | import com.snowalker.lock.redisson.constant.GlobalConstant; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.redisson.config.Config; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | /** 11 | * @author snowalker 12 | * @date 2018/7/12 13 | * @desc 哨兵集群方式Redis连接配置 14 | */ 15 | public class SentinelRedissonConfigStrategyImpl implements RedissonConfigStrategy { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(SentinelRedissonConfigStrategyImpl.class); 18 | 19 | @Override 20 | public Config createRedissonConfig(RedissonProperties redissonProperties) { 21 | Config config = new Config(); 22 | try { 23 | String address = redissonProperties.getAddress(); 24 | String password = redissonProperties.getPassword(); 25 | int database = redissonProperties.getDatabase(); 26 | String[] addrTokens = address.split(","); 27 | String sentinelAliasName = addrTokens[0]; 28 | /**设置redis配置文件sentinel.conf配置的sentinel别名*/ 29 | config.useSentinelServers() 30 | .setMasterName(sentinelAliasName); 31 | config.useSentinelServers().setDatabase(database); 32 | if (StringUtils.isNotBlank(password)) { 33 | config.useSentinelServers().setPassword(password); 34 | } 35 | /**设置sentinel节点的服务IP和端口*/ 36 | for (int i = 1; i < addrTokens.length; i++) { 37 | config.useSentinelServers().addSentinelAddress(GlobalConstant.REDIS_CONNECTION_PREFIX.getConstant_value() + addrTokens[i]); 38 | } 39 | LOGGER.info("初始化[sentinel]方式Config,redisAddress:" + address); 40 | } catch (Exception e) { 41 | LOGGER.error("sentinel Redisson init error", e); 42 | e.printStackTrace(); 43 | } 44 | return config; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.snowalker 7 | redis-distributed-lock-starter-demo 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | redis-distributed-lock-starter-demo 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.1.3.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | rctmq-spring 30 | 31 | 32 | guava 33 | com.google.guava 34 | 35 | 36 | commons-lang3 37 | org.apache.commons 38 | 39 | 40 | com.gyjx.marketing 41 | 0.0.1 42 | 43 | 44 | 45 | com.snowalker 46 | redis-distributed-lock-starter 47 | 1.2.0 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter-web 53 | 54 | 55 | 56 | org.springframework.boot 57 | spring-boot-starter-test 58 | test 59 | 60 | 61 | 62 | 63 | 64 | 65 | org.springframework.boot 66 | spring-boot-maven-plugin 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/src/main/java/com/snowalker/lock/redisson/config/strategy/MasterslaveRedissonConfigStrategyImpl.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock.redisson.config.strategy; 2 | 3 | import com.snowalker.lock.redisson.config.RedissonProperties; 4 | import com.snowalker.lock.redisson.constant.GlobalConstant; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.redisson.config.Config; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | /** 14 | * @author snowalker 15 | * @date 2018/7/12 16 | * @desc 主从方式Redisson配置 17 | * 连接方式:主节点,子节点,子节点 18 | * 格式为: 127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381 19 | */ 20 | public class MasterslaveRedissonConfigStrategyImpl implements RedissonConfigStrategy { 21 | 22 | private static final Logger LOGGER = LoggerFactory.getLogger(ClusterRedissonConfigStrategyImpl.class); 23 | 24 | @Override 25 | public Config createRedissonConfig(RedissonProperties redissonProperties) { 26 | Config config = new Config(); 27 | try { 28 | String address = redissonProperties.getAddress(); 29 | String password = redissonProperties.getPassword(); 30 | int database = redissonProperties.getDatabase(); 31 | String[] addrTokens = address.split(","); 32 | String masterNodeAddr = addrTokens[0]; 33 | /**设置主节点ip*/ 34 | config.useMasterSlaveServers().setMasterAddress(masterNodeAddr); 35 | if (StringUtils.isNotBlank(password)) { 36 | config.useMasterSlaveServers().setPassword(password); 37 | } 38 | config.useMasterSlaveServers().setDatabase(database); 39 | /**设置从节点,移除第一个节点,默认第一个为主节点*/ 40 | List slaveList = new ArrayList<>(); 41 | for (String addrToken : addrTokens) { 42 | slaveList.add(GlobalConstant.REDIS_CONNECTION_PREFIX.getConstant_value() + addrToken); 43 | } 44 | slaveList.remove(0); 45 | 46 | config.useMasterSlaveServers().addSlaveAddress((String[]) slaveList.toArray()); 47 | LOGGER.info("初始化[MASTERSLAVE]方式Config,redisAddress:" + address); 48 | } catch (Exception e) { 49 | LOGGER.error("MASTERSLAVE Redisson init error", e); 50 | e.printStackTrace(); 51 | } 52 | return config; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /redis-distributed-lock-demo-spring/src/main/resources/application-test.properties: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # 3 | # 启动端口号 4 | # 5 | ########################################################################## 6 | server.port=8080 7 | # app-name (need to modify) 8 | spring.application.name=alipay-gateway-server 9 | ######################################################################## 10 | # 11 | # 数据源配置 12 | # 13 | ######################################################################### 14 | # datasource-hikari 15 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver 16 | spring.datasource.url=${jdbc.url} 17 | spring.datasource.username=root 18 | spring.datasource.password=123456 19 | spring.datasource.type=com.zaxxer.hikari.HikariDataSource 20 | spring.datasource.default-auto-commit=true 21 | #指定updates是否自动提交 22 | spring.datasource.auto-commit=true 23 | spring.jpa.show-sql = true 24 | spring.datasource.maximum-pool-size=100 25 | spring.datasource.max-idle=10 26 | spring.datasource.max-wait=10000 27 | spring.datasource.min-idle=5 28 | spring.datasource.initial-size=5 29 | spring.datasource.validation-query=SELECT 1 30 | spring.datasource.test-on-borrow=false 31 | spring.datasource.test-while-idle=true 32 | # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 33 | spring.datasource.time-between-eviction-runs-millis=18800 34 | # 配置一个连接在池中最小生存的时间,单位是毫秒 35 | spring.datasource.minEvictableIdleTimeMillis=300000 36 | jdbc.url=jdbc:mysql://172.30.61.11:3306/alipay-gateway-server?useUnicode=true&characterEncoding=utf-8&useSSL=false 37 | ######################################################################## 38 | # 39 | # 日志配置 40 | # 41 | ######################################################################### 42 | logging.pattern.console=%-12(%d{yyyy-MM-dd HH:mm:ss.SSS}) |-%-5level [%thread] %c [%L] -| %msg%n 43 | logging.pattern.file=%-12(%d{yyyy-MM-dd HH:mm:ss.SSS}) |-%-5level [%thread] %c [%L] -| %msg%n 44 | logging.file=d:/log/alipay_gateway_server/console.log 45 | logging.level.com.gaoyang=DEBUG 46 | ######################################################################## 47 | # 48 | # dubbo服务配置 49 | # 50 | ######################################################################### 51 | spring.dubbo.application.name=rpc-config-service 52 | spring.dubbo.registry.address=zookeeper://127.0.0.1:2181 53 | spring.dubbo.scan=com.hispeed.development.service 54 | spring.dubbo.protocol.name=dubbo 55 | spring.dubbo.protocol.port=20880 56 | ######################################################################## 57 | # 58 | # mybatis配置 59 | # 60 | ######################################################################### 61 | mybatis.mapper-locations=classpath:mybatis/mapper/*Mapper.xml 62 | 63 | 64 | -------------------------------------------------------------------------------- /redis-distributed-lock-demo-spring/src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # 3 | # 启动端口号 4 | # 5 | ########################################################################## 6 | server.port=8080 7 | # app-name (need to modify) 8 | spring.application.name=alipay-gateway-server 9 | ######################################################################## 10 | # 11 | # 数据源配置 12 | # 13 | ######################################################################### 14 | # datasource-hikari 15 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver 16 | spring.datasource.url=${jdbc.url} 17 | spring.datasource.username=root 18 | spring.datasource.password=123456 19 | spring.datasource.type=com.zaxxer.hikari.HikariDataSource 20 | spring.datasource.default-auto-commit=true 21 | #指定updates是否自动提交 22 | spring.datasource.auto-commit=true 23 | spring.jpa.show-sql = true 24 | spring.datasource.maximum-pool-size=100 25 | spring.datasource.max-idle=10 26 | spring.datasource.max-wait=10000 27 | spring.datasource.min-idle=5 28 | spring.datasource.initial-size=5 29 | spring.datasource.validation-query=SELECT 1 30 | spring.datasource.test-on-borrow=false 31 | spring.datasource.test-while-idle=true 32 | # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 33 | spring.datasource.time-between-eviction-runs-millis=18800 34 | # 配置一个连接在池中最小生存的时间,单位是毫秒 35 | spring.datasource.minEvictableIdleTimeMillis=300000 36 | jdbc.url=jdbc:mysql://172.30.61.11:3306/alipay-gateway-server ?useUnicode=true&characterEncoding=utf-8&useSSL=false 37 | ######################################################################## 38 | # 39 | # 日志配置 40 | # 41 | ######################################################################### 42 | logging.pattern.console=%-12(%d{yyyy-MM-dd HH:mm:ss.SSS}) |-%-5level [%thread] %c [%L] -| %msg%n 43 | logging.pattern.file=%-12(%d{yyyy-MM-dd HH:mm:ss.SSS}) |-%-5level [%thread] %c [%L] -| %msg%n 44 | logging.file=d:/log/alipay_gateway_server/console.log 45 | logging.level.com.gaoyang=DEBUG 46 | ######################################################################## 47 | # 48 | # dubbo服务配置 49 | # 50 | ######################################################################### 51 | spring.dubbo.application.name=rpc-config-service 52 | spring.dubbo.registry.address=zookeeper://127.0.0.1:2181 53 | spring.dubbo.scan=com.hispeed.development.service 54 | spring.dubbo.protocol.name=dubbo 55 | spring.dubbo.protocol.port=20880 56 | ######################################################################## 57 | # 58 | # mybatis配置 59 | # 60 | ######################################################################### 61 | mybatis.mapper-locations=classpath:mybatis/mapper/*Mapper.xml 62 | 63 | 64 | -------------------------------------------------------------------------------- /redis-distributed-lock-core/src/main/java/com/snowalker/config/RedisPoolUtil.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.config; 2 | 3 | import redis.clients.jedis.Jedis; 4 | 5 | /** 6 | * @author snowalker 7 | * @date 2018-7-9 8 | * @desc 封装单机版Jedis工具类 9 | */ 10 | public class RedisPoolUtil { 11 | 12 | private RedisPoolUtil(){} 13 | 14 | private static RedisPool redisPool; 15 | 16 | public static String get(String key){ 17 | Jedis jedis = null; 18 | String result = null; 19 | try { 20 | jedis = RedisPool.getJedis(); 21 | result = jedis.get(key); 22 | } catch (Exception e){ 23 | e.printStackTrace(); 24 | } finally { 25 | if (jedis != null) { 26 | jedis.close(); 27 | } 28 | return result; 29 | } 30 | } 31 | 32 | public static Long setnx(String key, String value){ 33 | Jedis jedis = null; 34 | Long result = null; 35 | try { 36 | jedis = RedisPool.getJedis(); 37 | result = jedis.setnx(key, value); 38 | } catch (Exception e){ 39 | e.printStackTrace(); 40 | } finally { 41 | if (jedis != null) { 42 | jedis.close(); 43 | } 44 | return result; 45 | } 46 | } 47 | 48 | public static String getSet(String key, String value){ 49 | Jedis jedis = null; 50 | String result = null; 51 | try { 52 | jedis = RedisPool.getJedis(); 53 | result = jedis.getSet(key, value); 54 | } catch (Exception e){ 55 | e.printStackTrace(); 56 | } finally { 57 | if (jedis != null) { 58 | jedis.close(); 59 | } 60 | return result; 61 | } 62 | } 63 | 64 | public static Long expire(String key, int seconds){ 65 | Jedis jedis = null; 66 | Long result = null; 67 | try { 68 | jedis = RedisPool.getJedis(); 69 | result = jedis.expire(key, seconds); 70 | } catch (Exception e){ 71 | e.printStackTrace(); 72 | } finally { 73 | if (jedis != null) { 74 | jedis.close(); 75 | } 76 | return result; 77 | } 78 | } 79 | 80 | public static Long del(String key){ 81 | Jedis jedis = null; 82 | Long result = null; 83 | try { 84 | jedis = RedisPool.getJedis(); 85 | result = jedis.del(key); 86 | } catch (Exception e){ 87 | e.printStackTrace(); 88 | } finally { 89 | if (jedis != null) { 90 | jedis.close(); 91 | } 92 | return result; 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /redis-distributed-lock-core/src/main/java/com/snowalker/config/RedisPool.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.config; 2 | 3 | import com.snowalker.util.PropertiesUtil; 4 | import redis.clients.jedis.Jedis; 5 | import redis.clients.jedis.JedisPool; 6 | import redis.clients.jedis.JedisPoolConfig; 7 | 8 | /** 9 | * @author snowalker 10 | * @date 2018-7-9 11 | * @desc Redis单机模式连接池 12 | */ 13 | public class RedisPool { 14 | 15 | /**jedis连接池*/ 16 | private static JedisPool pool; 17 | /**最大连接数*/ 18 | private static Integer maxTotal; 19 | /**最大空闲连接数,在jedispool中最大的idle状态(空闲的)的jedis实例的个数*/ 20 | private static Integer maxIdle; 21 | /**最小空闲连接数,在jedispool中最小的idle状态(空闲的)的jedis实例的个数*/ 22 | private static Integer minIdle; 23 | /**在取连接时测试连接的可用性,在borrow一个jedis实例的时候,是否要进行验证操作,如果赋值true。则得到的jedis实例肯定是可以用的。*/ 24 | private static Boolean testOnBorrow; 25 | /**再还连接时不测试连接的可用性,在return一个jedis实例的时候,是否要进行验证操作,如果赋值true。则放回jedispool的jedis实例肯定是可以用的。*/ 26 | private static Boolean testOnReturn; 27 | /**redis服务端ip*/ 28 | private static String redisIp; 29 | /**redis服务端port*/ 30 | private static Integer redisPort; 31 | /**redis连接超时时间*/ 32 | private static Integer redisTimeout; 33 | 34 | static { 35 | init(); 36 | } 37 | 38 | private static void init() { 39 | maxTotal = Integer.parseInt(PropertiesUtil.getProperty("redis.max.total", "20")); 40 | maxIdle = Integer.parseInt(PropertiesUtil.getProperty("redis.max.idle","20")); 41 | minIdle = Integer.parseInt(PropertiesUtil.getProperty("redis.min.idle","10")); 42 | testOnBorrow = Boolean.parseBoolean(PropertiesUtil.getProperty("redis.test.borrow","true")); 43 | testOnReturn = Boolean.parseBoolean(PropertiesUtil.getProperty("redis.test.return","true")); 44 | redisTimeout = Integer.valueOf(PropertiesUtil.getProperty("redis.server.timeout", "3000")); 45 | 46 | redisIp = PropertiesUtil.getProperty("redis.ip"); 47 | if (redisIp == null) { 48 | throw new RuntimeException("请检查redis服务端ip配置项redis.ip是否配置"); 49 | } 50 | redisPort = Integer.parseInt(PropertiesUtil.getProperty("redis.port")); 51 | if (redisPort == null) { 52 | throw new RuntimeException("请检查redis服务端port配置项redis.port是否配置"); 53 | } 54 | 55 | JedisPoolConfig config = new JedisPoolConfig(); 56 | config.setMaxTotal(maxTotal); 57 | config.setMaxIdle(maxIdle); 58 | config.setMinIdle(minIdle); 59 | config.setTestOnBorrow(testOnBorrow); 60 | config.setTestOnReturn(testOnReturn); 61 | /**连接耗尽的时候,是否阻塞,false会抛出异常,true阻塞直到超时。默认为true*/ 62 | config.setBlockWhenExhausted(true); 63 | 64 | pool = new JedisPool(config, redisIp, redisPort, redisTimeout); 65 | } 66 | 67 | public static Jedis getJedis(){ 68 | return pool.getResource(); 69 | } 70 | 71 | public static void close(Jedis jedis){ 72 | jedis.close(); 73 | } 74 | 75 | public static void returnBrokenResource(Jedis jedis){ 76 | pool.returnBrokenResource(jedis); 77 | } 78 | 79 | public static void returnResource(Jedis jedis){ 80 | pool.returnResource(jedis); 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/src/main/java/com/snowalker/lock/redisson/RedissonManager.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock.redisson; 2 | 3 | import com.google.common.base.Preconditions; 4 | import com.snowalker.lock.redisson.config.RedissonProperties; 5 | import com.snowalker.lock.redisson.config.strategy.*; 6 | import com.snowalker.lock.redisson.constant.RedisConnectionType; 7 | import org.redisson.Redisson; 8 | import org.redisson.config.Config; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | /** 13 | * @author snowalker 14 | * @date 2018/7/10 15 | * @desc Redisson核心配置,用于提供初始化的redisson实例 16 | */ 17 | public class RedissonManager { 18 | 19 | private static final Logger LOGGER = LoggerFactory.getLogger(Redisson.class); 20 | 21 | private Config config = new Config(); 22 | 23 | private Redisson redisson = null; 24 | 25 | public RedissonManager() {} 26 | 27 | public RedissonManager(RedissonProperties redissonProperties) { 28 | try { 29 | config = RedissonConfigFactory.getInstance().createConfig(redissonProperties); 30 | redisson = (Redisson) Redisson.create(config); 31 | } catch (Exception e) { 32 | LOGGER.error("Redisson init error", e); 33 | throw new IllegalArgumentException("please input correct configurations," + 34 | "connectionType must in standalone/sentinel/cluster/masterslave"); } 35 | } 36 | 37 | public Redisson getRedisson() { 38 | return redisson; 39 | } 40 | 41 | /** 42 | * Redisson连接方式配置工厂 43 | * 双重检查锁 44 | */ 45 | static class RedissonConfigFactory { 46 | 47 | private RedissonConfigFactory() {} 48 | 49 | private static volatile RedissonConfigFactory factory = null; 50 | 51 | public static RedissonConfigFactory getInstance() { 52 | if (factory == null) { 53 | synchronized (Object.class) { 54 | if (factory == null) { 55 | factory = new RedissonConfigFactory(); 56 | } 57 | } 58 | } 59 | return factory; 60 | } 61 | 62 | private Config config = new Config(); 63 | 64 | /** 65 | * 根据连接类型获取对应连接方式的配置,基于策略模式 66 | * @param redissonProperties 67 | * @return Config 68 | */ 69 | Config createConfig(RedissonProperties redissonProperties) { 70 | Preconditions.checkNotNull(redissonProperties); 71 | Preconditions.checkNotNull(redissonProperties.getAddress(), "redisson.lock.server.address cannot be NULL!"); 72 | Preconditions.checkNotNull(redissonProperties.getType(), "redisson.lock.server.password cannot be NULL"); 73 | Preconditions.checkNotNull(redissonProperties.getDatabase(), "redisson.lock.server.database cannot be NULL"); 74 | String connectionType = redissonProperties.getType(); 75 | /**声明配置上下文*/ 76 | RedissonConfigContext redissonConfigContext = null; 77 | if (connectionType.equals(RedisConnectionType.STANDALONE.getConnection_type())) { 78 | redissonConfigContext = new RedissonConfigContext(new StandaloneRedissonConfigStrategyImpl()); 79 | } else if (connectionType.equals(RedisConnectionType.SENTINEL.getConnection_type())) { 80 | redissonConfigContext = new RedissonConfigContext(new SentinelRedissonConfigStrategyImpl()); 81 | } else if (connectionType.equals(RedisConnectionType.CLUSTER.getConnection_type())) { 82 | redissonConfigContext = new RedissonConfigContext(new ClusterRedissonConfigStrategyImpl()); 83 | } else if (connectionType.equals(RedisConnectionType.MASTERSLAVE.getConnection_type())) { 84 | redissonConfigContext = new RedissonConfigContext(new MasterslaveRedissonConfigStrategyImpl()); 85 | } else { 86 | throw new IllegalArgumentException("创建Redisson连接Config失败!当前连接方式:" + connectionType); 87 | } 88 | return redissonConfigContext.createRedissonConfig(redissonProperties); 89 | } 90 | } 91 | 92 | } 93 | 94 | 95 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.snowalker 7 | redis-distributed-lock-starter 8 | 1.2.0 9 | jar 10 | 11 | redis-distributed-lock-starter 12 | redis distributed lock starter Redission 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 1.5.3.RELEASE 18 | 19 | 20 | 21 | 22 | 1.8.13 23 | 1.8.13 24 | 3.4 25 | 32.0.0-jre 26 | 3.4 27 | UTF-8 28 | UTF-8 29 | 1.8 30 | 31 | 32 | 33 | 34 | com.google.guava 35 | guava 36 | ${google-guava} 37 | 38 | 39 | 40 | org.aspectj 41 | aspectjrt 42 | ${aspecjrt} 43 | 44 | 45 | 46 | org.aspectj 47 | aspectjweaver 48 | ${aspectjweaver} 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-starter-test 57 | test 58 | 59 | 60 | 61 | org.springframework.boot 62 | spring-boot-starter-logging 63 | 64 | 65 | 66 | javax.annotation 67 | javax.annotation-api 68 | 1.3.2 69 | 70 | 71 | 72 | org.redisson 73 | redisson 74 | 3.5.4 75 | 76 | 77 | org.apache.commons 78 | commons-lang3 79 | ${apache-common-lang3} 80 | 81 | 82 | 83 | 84 | 85 | 86 | maven-source-plugin 87 | 3.0.1 88 | 89 | true 90 | 91 | 92 | 93 | compile 94 | 95 | jar 96 | 97 | 98 | 99 | 100 | 101 | org.apache.maven.plugins 102 | maven-compiler-plugin 103 | 104 | 8 105 | 8 106 | 107 | 108 | 109 | 110 | 111 | ${project.build.directory}/classes 112 | src/main/resources 113 | true 114 | 115 | **/*.xml 116 | **/*.* 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /redis-distributed-lock-core/src/main/java/com/snowalker/lock/RedisDistributedLock.java: -------------------------------------------------------------------------------- 1 | package com.snowalker.lock; 2 | 3 | import com.snowalker.config.RedisPoolUtil; 4 | import com.snowalker.util.PropertiesUtil; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | /** 10 | * @author snowalker 11 | * @date 2018-7-9 12 | * @desc redis分布式锁核心实现 13 | */ 14 | public class RedisDistributedLock implements DistributedLock { 15 | 16 | /**默认锁超时时间为10S*/ 17 | private static final int EXPIRE_SECONDS = 50; 18 | private static final Logger log = LoggerFactory.getLogger(RedisDistributedLock.class); 19 | 20 | private RedisDistributedLock() { 21 | } 22 | 23 | private volatile static RedisDistributedLock redisDistributedLock; 24 | 25 | public static RedisDistributedLock getInstance() { 26 | if (redisDistributedLock == null) { 27 | synchronized (RedisDistributedLock.class) { 28 | redisDistributedLock = new RedisDistributedLock(); 29 | } 30 | } 31 | return redisDistributedLock; 32 | } 33 | 34 | /** 35 | * 加锁 36 | * 37 | * @param lockName 38 | * @return 返回true表示加锁成功,执行业务逻辑,执行完毕需要主动释放锁,否则就需要等待锁超时重新争抢 39 | * 返回false标识加锁失败,阻塞并继续尝试获取锁 40 | */ 41 | @Override 42 | public boolean lock(String lockName) { 43 | /**1.使用setNx开始加锁*/ 44 | log.info("开始获取Redis分布式锁流程,lockName={},CurrentThreadName={}", lockName, Thread.currentThread().getName()); 45 | long lockTimeout = Long.parseLong(PropertiesUtil.getProperty("redis.lock.timeout", "5")); 46 | /**redis中锁的值为:当前时间+超时时间*/ 47 | Long lockResult = RedisPoolUtil.setnx(lockName, String.valueOf(System.currentTimeMillis() + lockTimeout)); 48 | 49 | if (lockResult != null && lockResult.intValue() == 1) { 50 | log.info("setNx获取分布式锁[成功],threadName={}", Thread.currentThread().getName()); 51 | RedisPoolUtil.expire(lockName, EXPIRE_SECONDS); 52 | return true; 53 | } else { 54 | log.info("setNx获取分布式锁[失败],threadName={}", Thread.currentThread().getName()); 55 | // return tryLock(lockName, lockTimeout); 56 | return false; 57 | } 58 | } 59 | 60 | private boolean tryLock(String lockName, long lockTimeout) { 61 | /** 62 | * 2.加锁失败后再次尝试 63 | * 2.1获取锁失败,继续判断,判断时间戳,看是否可以重置并获取到锁 64 | * setNx结果小于当前时间,表明锁已过期,可以再次尝试加锁 65 | */ 66 | String lockValueStr = RedisPoolUtil.get(lockName); 67 | Long lockValueATime = Long.parseLong(lockValueStr); 68 | log.info("lockValueATime为:" + lockValueATime); 69 | if (lockValueStr != null && lockValueATime < System.currentTimeMillis()) { 70 | 71 | /**2.2再次用当前时间戳getset--->将给定 key 的值设为 value,并返回 key 的旧值(old value) 72 | * 通过getset重设锁对应的值: 新的当前时间+超时时间,并返回旧的锁对应值 73 | */ 74 | String getSetResult = RedisPoolUtil.getSet(lockName, String.valueOf(System.currentTimeMillis() + lockTimeout)); 75 | log.info("lockValueBTime为:" + Long.parseLong(getSetResult)); 76 | if (getSetResult == null || (getSetResult != null && StringUtils.equals(lockValueStr, getSetResult))) { 77 | /** 78 | *2.3旧值判断,是否可以获取锁 79 | *当key没有旧值时,即key不存在时,返回nil ->获取锁,设置锁过期时间 80 | */ 81 | log.info("获取Redis分布式锁[成功],lockName={},CurrentThreadName={}", 82 | lockName, Thread.currentThread().getName()); 83 | RedisPoolUtil.expire(lockName, EXPIRE_SECONDS); 84 | return true; 85 | } else { 86 | log.info("获取锁失败,lockName={},CurrentThreadName={}", 87 | lockName, Thread.currentThread().getName()); 88 | return false; 89 | } 90 | } else { 91 | /**3.锁未超时,获取锁失败*/ 92 | log.info("当前锁未失效!!!!,竞争失败,继续持有之前的锁,lockName={},CurrentThreadName={}", 93 | lockName, Thread.currentThread().getName()); 94 | return false; 95 | } 96 | } 97 | 98 | /** 99 | * 解锁 100 | * 101 | * @param lockName 102 | */ 103 | @Override 104 | public boolean release(String lockName) { 105 | Long result = RedisPoolUtil.del(lockName); 106 | if (result != null && result.intValue() == 1) { 107 | log.info("删除Redis分布式锁成功,锁已释放, key= :{}", lockName); 108 | return true; 109 | } 110 | log.info("删除Redis分布式锁失败,锁未释放, key= :{}", lockName); 111 | return false; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /redis-distributed-lock-demo-spring/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 1.5.3.RELEASE 9 | 10 | 11 | 4.0.0 12 | 13 | redis-distributed-lock-demo-spring 14 | 1.0.0 15 | com.snowalker 16 | 17 | redis-distributed-lock-demo-spring 18 | 19 | http://www.example.com 20 | 21 | 22 | 1.0.0 23 | 1.8.10 24 | 1.8.10 25 | 1.3.0 26 | 2.3.4 27 | 1.0.0 28 | 1.0.29 29 | 1.2.32 30 | UTF-8 31 | UTF-8 32 | 1.7 33 | 1.7 34 | 1.7 35 | Maven.19ego.cn:8081 36 | 37 | 38 | 39 | 40 | com.snowalker 41 | redis-distributed-lock-starter 42 | 1.2.0 43 | 44 | 45 | com.snowalker 46 | redis-distributed-lock-core 47 | 1.0.0 48 | 49 | 50 | 51 | junit 52 | junit 53 | 4.13.1 54 | test 55 | 56 | 57 | 58 | org.springframework.boot 59 | spring-boot-starter-data-redis 60 | 61 | 62 | 63 | org.springframework.boot 64 | spring-boot-starter-web 65 | 66 | 67 | 68 | org.springframework.boot 69 | spring-boot-starter-test 70 | test 71 | 72 | 73 | 74 | org.springframework.boot 75 | spring-boot-starter-jdbc 76 | 77 | 78 | org.apache.tomcat 79 | tomcat-jdbc 80 | 81 | 82 | 83 | 84 | 85 | org.mybatis.spring.boot 86 | mybatis-spring-boot-starter 87 | ${mybatis-springboot.version} 88 | 89 | 90 | 91 | mysql 92 | mysql-connector-java 93 | 8.0.28 94 | 95 | 96 | com.zaxxer 97 | HikariCP 98 | 2.6.1 99 | compile 100 | 101 | 102 | com.alibaba 103 | fastjson 104 | 1.2.83 105 | 106 | 107 | 108 | 109 | ${project.name}-${project.version} 110 | 111 | 112 | org.springframework.boot 113 | spring-boot-maven-plugin 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter-demo/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /redis-distributed-lock-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 4.0.0 7 | 8 | com.snowalker 9 | redis-distributed-lock-core 10 | 1.0.0 11 | 12 | redis-distributed-lock-core 13 | 14 | http://www.example.com 15 | 16 | 17 | 1.8.10 18 | 1.8.10 19 | 3.4 20 | 20.0 21 | 2.9.0 22 | 1.7.25 23 | UTF-8 24 | 1.7 25 | 1.7 26 | 27 | 28 | 29 | 30 | junit 31 | junit 32 | 4.13.1 33 | test 34 | 35 | 36 | 37 | 38 | org.aspectj 39 | aspectjrt 40 | ${aspecjrt} 41 | 42 | 43 | 44 | org.aspectj 45 | aspectjweaver 46 | ${aspectjweaver} 47 | 48 | 49 | 50 | org.apache.commons 51 | commons-lang3 52 | ${apache-common-lang3} 53 | 54 | 55 | com.google.guava 56 | guava 57 | ${google-guava} 58 | 59 | 60 | 61 | redis.clients 62 | jedis 63 | ${jedis} 64 | 65 | 66 | 67 | org.slf4j 68 | slf4j-api 69 | ${slf4j-api} 70 | 71 | 72 | 73 | org.springframework 74 | spring-context 75 | 4.3.18.RELEASE 76 | provided 77 | 78 | 79 | 80 | org.springframework 81 | spring-core 82 | 5.2.24.RELEASE 83 | provided 84 | 85 | 86 | 87 | org.redisson 88 | redisson 89 | 3.5.4 90 | 91 | 92 | javax.annotation 93 | javax.annotation-api 94 | 1.3.2 95 | compile 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | maven-clean-plugin 105 | 3.0.0 106 | 107 | 108 | 109 | maven-resources-plugin 110 | 3.0.2 111 | 112 | 113 | maven-compiler-plugin 114 | 3.7.0 115 | 116 | 117 | maven-surefire-plugin 118 | 2.20.1 119 | 120 | 121 | maven-jar-plugin 122 | 3.0.2 123 | 124 | 125 | maven-install-plugin 126 | 2.5.2 127 | 128 | 129 | maven-deploy-plugin 130 | 2.8.2 131 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter/mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /redis-distributed-lock-starter-demo/mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # redis-distributed-lock 2 | > redis分布式锁工具包,提供纯Java方式调用,支持传统Spring工程, 3 | > 为spring boot应用提供了starter,更方便快捷的调用。 4 | ## 项目结构 5 | 6 | [redis-distributed-lock-core](http://wuwenliang.net/2018/07/08/%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E7%9A%84%E5%A4%9A%E7%A7%8D%E5%AE%9E%E7%8E%B0/)              原生redis分布式锁实现,支持注解,不推荐项目中使用,仅供学习使用 7 | 8 | redis-distributed-lock-demo-spring   redis-distributed-lock-core 调用实例,仅供学习 9 | 10 | [redis-distributed-lock-starter](./redis-distributed-lock-starter/readme.md)             基于Redisson的分布式锁spring starter实现,可用于实际项目中 11 | 12 | [redis-distributed-lock-starter-demo](./redis-distributed-lock-starter-demo/readme.md)   redis-distributed-lock-starter调用实例 13 | 14 | ## 文档 15 | ### springboot应用(直接编程方式) 16 | 0. 配置文件application.properties中引入 17 | 18 | redisson.lock.server.address=127.0.0.1:6379 19 | redisson.lock.server.type=standalone 20 | 21 | 1. 针对springboot应用只需要引入依赖 22 | 23 | 24 | 25 | com.snowalker 26 | redis-distributed-lock-starter 27 | 1.0.0 28 | 29 | 2. 直接编程方式调用如下,在需要加锁的定时任务中,注入 **RedissonLock** 实体,即可进行加锁、解锁等操作。 30 |
锁自动释放时间默认为10秒,这个时间需要你根据自己的业务执行时间自行指定。 31 | 32 | @Autowired 33 | RedissonLock redissonLock; 34 | 35 | @Scheduled(cron = "${redis.lock.cron}") 36 | public void execute() throws InterruptedException { 37 | if (redissonLock.lock("redisson", 10)) { 38 | LOGGER.info("[ExecutorRedisson]--执行定时任务开始,休眠三秒"); 39 | Thread.sleep(3000); 40 | System.out.println("=======================业务逻辑============================="); 41 | LOGGER.info("[ExecutorRedisson]--执行定时任务结束,休眠三秒"); 42 | redissonLock.release("redisson"); 43 | } else { 44 | LOGGER.info("[ExecutorRedisson]获取锁失败"); 45 | } 46 | } 47 | 48 | 3. 你可以改变测试demo的端口,起多个查看日志,能够看到同一时刻只有一个实例获取锁成功并执行业务逻辑 49 | 50 | 2018-07-10 23:00:12.810 |-INFO [main] org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer [198] -| Tomcat started on port(s): 8888 (http) 51 | 2018-07-10 23:00:12.814 |-INFO [main] com.snowalker.RedisDistributedLockStarterDemoApplication [57] -| Started RedisDistributedLockStarterDemoApplication in 2.684 seconds (JVM running for 3.038) 52 | 2018-07-10 23:00:15.033 |-INFO [pool-3-thread-1] com.snowalker.lock.redisson.RedissonLock [35] -| 获取Redisson分布式锁[成功],lockName=redisson 53 | 2018-07-10 23:00:15.034 |-INFO [pool-3-thread-1] com.snowalker.executor.ExecutorRedissonNormal [27] -| [ExecutorRedisson]--执行定时任务开始,休眠三秒 54 | =======================业务逻辑============================= 55 | 2018-07-10 23:00:18.035 |-INFO [pool-3-thread-1] com.snowalker.executor.ExecutorRedissonNormal [30] -| [ExecutorRedisson]--执行定时任务结束,休眠三秒 56 | 2018-07-10 23:00:20.005 |-INFO [pool-3-thread-1] com.snowalker.lock.redisson.RedissonLock [35] -| 获取Redisson分布式锁[成功],lockName=redisson 57 | 2018-07-10 23:00:20.006 |-INFO [pool-3-thread-1] com.snowalker.executor.ExecutorRedissonNormal [27] -| [ExecutorRedisson]--执行定时任务开始,休眠三秒 58 | =======================业务逻辑============================= 59 | ### springboot应用(注解方式) 60 | 1. 前提条件同样是要引入依赖 61 | 62 | 63 | 64 | com.snowalker 65 | redis-distributed-lock-starter 66 | 1.0.0 67 | 68 | 2. 注解方式调用如下,在需要加锁的定时任务的执行方法头部,添加 **@DistributedLock(value = "redis-lock", expireSeconds = 11)** 69 | 即可进行加锁、解锁等操作。
锁自动释放时间默认为10秒,这个时间需要你根据自己的业务执行时间自行指定。 70 |
我这里以spring schedule定时任务为例,用其他的定时任务同理,只需要添加注解。 71 | 72 | @Scheduled(cron = "${redis.lock.cron}") 73 | @DistributedLock(value = "redis-lock", expireSeconds = 11) 74 | public void execute() throws InterruptedException { 75 | LOGGER.info("[ExecutorRedisson]--执行定时任务开始,休眠三秒"); 76 | Thread.sleep(3000); 77 | System.out.println("=======================业务逻辑============================="); 78 | LOGGER.info("[ExecutorRedisson]--执行定时任务结束,休眠三秒"); 79 | } 80 | 81 | 3. 你可以改变测试demo的端口,起多个查看日志,能够看到同一时刻只有一个实例获取锁成功并执行业务逻辑 82 | 83 | 2018-07-11 09:48:06.330 |-INFO [main] com.snowalker.RedisDistributedLockStarterDemoApplication [57] -| Started RedisDistributedLockStarterDemoApplication in 3.901 seconds (JVM running for 4.356) 84 | 2018-07-11 09:48:10.006 |-INFO [pool-3-thread-1] com.snowalker.lock.redisson.annotation.DistributedLockHandler [32] -| [开始]执行RedisLock环绕通知,获取Redis分布式锁开始 85 | 2018-07-11 09:48:10.622 |-INFO [pool-3-thread-1] com.snowalker.lock.redisson.RedissonLock [35] -| 获取Redisson分布式锁[成功],lockName=redis-lock 86 | 2018-07-11 09:48:10.622 |-INFO [pool-3-thread-1] com.snowalker.lock.redisson.annotation.DistributedLockHandler [39] -| 获取Redis分布式锁[成功],加锁完成,开始执行业务逻辑... 87 | 2018-07-11 09:48:10.625 |-INFO [pool-3-thread-1] com.snowalker.executor.ExecutorRedissonAnnotation [22] -| [ExecutorRedisson]--执行定时任务开始,休眠三秒 88 | =======================业务逻辑============================= 89 | 2018-07-11 09:48:13.625 |-INFO [pool-3-thread-1] com.snowalker.executor.ExecutorRedissonAnnotation [25] -| [ExecutorRedisson]--执行定时任务结束,休眠三秒 90 | 2018-07-11 09:48:13.627 |-INFO [pool-3-thread-1] com.snowalker.lock.redisson.annotation.DistributedLockHandler [46] -| 释放Redis分布式锁[成功],解锁完成,结束业务逻辑... 91 | 2018-07-11 09:48:13.628 |-INFO [pool-3-thread-1] com.snowalker.lock.redisson.annotation.DistributedLockHandler [50] -| [结束]执行RedisLock环绕通知 92 | 93 | ## application.properties配置方式(yaml同理) 94 | ### redisson分布式锁配置--单机 95 | 96 | redisson.lock.server.address=127.0.0.1:6379 97 | redisson.lock.server.type=standalone 98 | redisson.lock.server.password= 99 | redisson.lock.server.database=1 100 | 101 | ### redisson分布式锁配置--哨兵 102 | **redisson.lock.server.address** 格式为: sentinel.conf配置里的sentinel别名,sentinel1节点的服务IP和端口,sentinel2节点的服务IP和端口,sentinel3节点的服务IP和端口 103 |
比如sentinel.conf里配置为sentinel monitor my-sentinel-name 127.0.0.1 6379 2,那么这里就配置my-sentinel-name 104 | 105 | redisson.server.address=my-sentinel-name,127.0.0.1:26379,127.0.0.1:26389,127.0.0.1:26399 106 | redisson.server.type=sentinel 107 | redisson.lock.server.password= 108 | redisson.lock.server.database=1 109 | 110 | ### redisson分布式锁配置--集群方式 111 | cluster方式至少6个节点(3主3从,3主做sharding,3从用来保证主宕机后可以高可用) 112 |
地址格式为: 127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381,127.0.0.1:6382,127.0.0.1:6383,127.0.0.1:6384 113 | 114 | redisson.server.address=127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381,127.0.0.1:6382,127.0.0.1:6383,127.0.0.1:6384 115 | redisson.server.type=cluster 116 | redisson.lock.server.password= 117 | redisson.lock.server.database=1 118 | 119 | ### redisson分布式锁配置--主从 120 | 地址格式为**主节点,子节点,子节点** 121 |
比如:127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381 122 |
代表主节点:127.0.0.1:6379,从节点127.0.0.1:6380,127.0.0.1:6381 123 | 124 | redisson.server.address=127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381 125 | redisson.server.type=masterslave 126 | redisson.lock.server.password= 127 | redisson.lock.server.database=1 128 | 129 | ## 参考资料 130 | 131 | [自己写分布式锁-基于redission](http://wuwenliang.net/2018/12/07/%E8%87%AA%E5%B7%B1%E5%86%99%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81-%E5%9F%BA%E4%BA%8Eredission/) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------