├── 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 | | redis.max.total |
14 | 最大连接数 |
15 |
16 |
17 | | redis.max.idle |
18 | 最大空闲连接数,在jedispool中最大的idle状态(空闲的)的jedis实例的个数 |
19 |
20 |
21 | | redis.min.idle |
22 | 最小空闲连接数,在jedispool中最小的idle状态(空闲的)的jedis实例的个数 |
23 |
24 |
25 | | redis.test.borrow |
26 | 在取连接时测试连接的可用性,在borrow一个jedis实例的时候, 是否要进行验证操作,如果赋值true。则得到的jedis实例肯定是可以用的 |
27 |
28 |
29 | | redis.test.return |
30 | 再还连接时不测试连接的可用性, 在return一个jedis实例的时候,是否要进行验证操作,如果赋值true。则放回jedispool的jedis实例肯定是可以用的。 |
31 |
32 |
33 | | redis.ip |
34 | redis服务端ip |
35 |
36 |
37 | | redis.port |
38 | redis服务端port |
39 |
40 |
41 | | redis.server.timeout |
42 | redis连接超时时间 |
43 |
44 |
45 | | redis.lock.timeout |
46 | 锁超时时间 |
47 |
48 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------