Skip to content

Commit

Permalink
feat($Redis): create the demo for Redis distributed lock
Browse files Browse the repository at this point in the history
  • Loading branch information
johnnymillergh committed Feb 26, 2022
1 parent 85bf9bc commit 74c54b3
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
* Description: AuthCenterApplicationTests.
*
* @author 钟俊 (zhongjun), email: zhongjun@toguide.cn, date: 12/21/2020 3:08 PM
* @see <a href='https://www.baeldung.com/spring-boot-testing'>Testing in Spring Boot</a>
*/
@Slf4j
@SpringBootTest
Expand All @@ -34,7 +35,7 @@ void mockLogin() {
user.setUsername("ijohnnymiller");
val authenticationToken = new UsernamePasswordAuthenticationToken(
UserPrincipal.create(user, new ArrayList<>(), new ArrayList<>()), 12345678);
String jwt = jwtService.createJwt(authenticationToken, false);
String jwt = this.jwtService.createJwt(authenticationToken, false);
log.info("Generated JWT: {}", jwt);
Assertions.assertTrue(StrUtil.isNotBlank(jwt));
}
Expand Down
6 changes: 6 additions & 0 deletions auth-center/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@
<artifactId>spring-test</artifactId>
</dependency>

<!-- Spring Integration -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-redis</artifactId>
</dependency>

<!-- ORM Library -->
<dependency>
<groupId>com.baomidou</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ spring:
timeout: 10000ms
client-type: LETTUCE
lettuce:
host: localhost
port: 6379
password: maf@redis
pool:
max-active: 20
max-idle: 10
Expand All @@ -112,16 +115,6 @@ spring:
clusterCheckinInterval: 3000
useProperties: false

redis:
master:
host: localhost
port: 6379
password: maf@redis
slaves:
- host: localhost
port: 6380
password: maf@redis

minio:
endpoint: http://localhost
port: 9000
Expand Down
6 changes: 6 additions & 0 deletions maf-mis/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@
<artifactId>spring-test</artifactId>
</dependency>

<!-- Spring Integration -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-redis</artifactId>
</dependency>

<!-- ORM Library -->
<dependency>
<groupId>com.baomidou</groupId>
Expand Down
1 change: 1 addition & 0 deletions spring-cloud-starter/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-redis</artifactId>
<scope>provided</scope>
</dependency>

<!-- OSS Dependencies -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.exceptions.PersistenceException;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.*;
import org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
Expand All @@ -52,6 +54,8 @@
* Description: MediaStreamingAutoConfiguration, change description here.
*
* @author Johnny Miller (锺俊), email: johnnysviva@outlook.com, date: 10/19/2020 2:51 PM
* @see
* <a href='https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.developing-auto-configuration'>9. Creating Your Own Auto-configuration</a>
**/
@Slf4j
@IntegrationComponentScan
Expand All @@ -67,7 +71,6 @@
WebMvcConfiguration.class,
MyBatisPlusConfiguration.class,
RedisConfiguration.class,
DistributedLockConfiguration.class,
ElasticsearchConfiguration.class,
WebSecurityConfiguration.class,
RestTemplateConfiguration.class,
Expand All @@ -82,6 +85,7 @@
OpenApiConfiguration.class,
OpenFeignConfiguration.class
})
@ImportAutoConfiguration(IntegrationAutoConfiguration.class)
public class MafAutoConfiguration {
private static final String INITIAL_MESSAGE = "Initial bean: '{}'";

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.integration.redis.util.RedisLockRegistry;

/**
* Description: RedisConfiguration, change description here.
Expand All @@ -38,10 +39,10 @@
})
@ConditionalOnClass({RedisConnectionFactory.class})
public class RedisConfiguration {
private static final String REGISTRY_KEY = "redis-lock";
private final RedisMasterSlaveReplicationProperties redisMasterSlaveReplicationProperties;
private final ObjectMapper objectMapper;


/**
* Redis connection factory lettuce connection factory.
*
Expand Down Expand Up @@ -80,6 +81,8 @@ public LettuceConnectionFactory redisConnectionFactory() {
* @param redisConnectionFactory the redis connection factory
* @return RedisTemplate redis template
* @author Johnny Miller (锺俊), email: johnnysviva@outlook.com, date: 12/30/2020 1:18 PM
* @see
* <a href='https://docs.spring.io/spring-data/data-redis/docs/current/reference/html/#redis:template'>Working with Objects through RedisTemplate</a>
*/
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
Expand All @@ -106,6 +109,8 @@ public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisC
* @param connectionFactory the reactive redis connection factory
* @return the reactive redis template
* @author Johnny Miller (锺俊), email: johnnysviva@outlook.com, date: 12/30/2020 1:43 PM
* @see
* <a href='https://docs.spring.io/spring-data/data-redis/docs/current/reference/html/#redis:reactive:template'>Working with Objects through ReactiveRedisTemplate</a>
*/
@Bean
ReactiveRedisTemplate<Object, Object> reactiveRedisTemplate(ReactiveRedisConnectionFactory connectionFactory) {
Expand All @@ -119,4 +124,29 @@ ReactiveRedisTemplate<Object, Object> reactiveRedisTemplate(ReactiveRedisConnect
.build();
return new ReactiveRedisTemplate<>(connectionFactory, serializationContext);
}

/**
* Redis distributed lock registry.
*
* @param redisConnectionFactory the redis connection factory
* @return the redis lock registry
* @see
* <a href='https://docs.spring.io/spring-integration/docs/current/reference/html/redis.html#redis-lock-registry'>Redis Lock Registry</a>
*/
@Bean(destroyMethod = "destroy")
@ConditionalOnClass({RedisLockRegistry.class})
public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) {
val redisLockRegistry = new RedisLockRegistry(redisConnectionFactory, REGISTRY_KEY);
log.warn("RedisLockRegistry bean is created. {}", redisLockRegistry);
return redisLockRegistry;
}

@Bean
@ConditionalOnClass({RedisLockRegistry.class})
public RedisDistributedLockDemoController redisDistributedLockDemoController(
RedisLockRegistry redisLockRegistry
) {
log.warn("RedisDistributedLockDemoController is created");
return new RedisDistributedLockDemoController(redisLockRegistry);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.jmsoftware.maf.springcloudstarter.redis;

import cn.hutool.core.util.RandomUtil;
import com.jmsoftware.maf.common.bean.ResponseBodyBean;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

/**
* <h1>RedisDistributedLockDemoController</h1>
* <p>
* Change description here.
*
* @author Johnny Miller (鍾俊), email: johnnysviva@outlook.com, 2/26/22 2:31 PM
**/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/redis/distributed-lock")
public class RedisDistributedLockDemoController {
private final RedisLockRegistry redisLockRegistry;

@GetMapping("/resource/{resourceKey}/{autoUnlock}")
public ResponseBodyBean<String> accessRaceResource(
@PathVariable String resourceKey,
@PathVariable boolean autoUnlock
) {
return ResponseBodyBean.ofSuccess(this.lockRaceResource(resourceKey, autoUnlock).toString());
}

@SneakyThrows
private Lock lockRaceResource(String key, boolean autoUnlock) {
val lock = this.redisLockRegistry.obtain(key);
log.info("Obtained the lock from the registry: {}, Key: {}", lock, key);
val acquiredLock = lock.tryLock(3, TimeUnit.SECONDS);
if (acquiredLock && autoUnlock) {
log.warn("Acquired the lock. Mocking to do busy computes. Will release the lock automatically");
Thread.sleep(RandomUtil.randomInt(10000));
lock.unlock();
log.warn("Released the lock. {}", lock);
}
log.info("Lock: {}, Key: {}, acquiredLock: {}", lock, key, acquiredLock);
return lock;
}
}

0 comments on commit 74c54b3

Please sign in to comment.