Redis
- Remote Dictionary Server
- Key - Value 기반의 오픈 소스 In - Memory NoSQL 데이터베이스
- Key - Value 기반으로 쿼리를 따로 작성할 필요 없이 결과를 바로 가져올 수 있습니다.
- 메모리에서 데이터를 처리하기 때문에 속도가 빠릅니다.
- 주로 동시성 제어(Lock)나 세션, 캐시 등으로 사용됩니다.
Redis Collection (데이터 구조)
String | 가장 일반적인 형태로, key - value 로 저장하는 형태 |
List | Array 형식의 데이터 구조로 List를 사용하면 처음과 끝에 데이터를 넣고 빼는것은 속도가 빠르지만 중간에 데이터를 삽입할 때는 어려움이 있습니다. |
Set | 순서가 없는 Strings 데이터 집합으로 Sets 에서는 중복된 데이터는 하나로 처리하기 때문에, 중복에 대한 걱정을 할 필요가 없습니다. |
Sorted Set | 위의 Sets와 같은 구조이지만 Score를 통해 순서를 정할 수 있습니다. Sorted Sets를 사용하면 Leaderboard와 같은 기능을 쉽게 구현할 수 있습니다. |
Hashes | Key-Value 구조를 여러개 가진 object 타입을 저장하기 좋은 구조입니다. |
Redis 특징
- In - Memory 기반
- 저장 용량은 적지만 빠른 속도를 가지고 있습니다.
- 휘발성입니다.
- NoSQL & Cache 솔루션
- 명시적으로 삭제나 expire(만료)를 설정하지 않으면 데이터는 삭제되지 않습니다.
- 여러 대의 서버 구성이 가능합니다
- 마스터 - 슬레이브 구조
- 1개의 싱글 쓰레드로 수행되기 때문에 서버 하나에 여러개의 Redis 서버를 띄울 수 있습니다.
- 싱글 쓰레드이기 때문에 동시에 처리할 수 있는 명령어는 하나입니다.
- 데이터베이스 or Cache로 사용됩니다.
Embedded Redis를 이용한 SpinLock 실습
- Redis 연습하기위해 Embedded Redis로 사용합니다.
- SpinLock을 활용한 동시성 제어 및 동시성 제어를 AOP를 활용하여 실습하는데 사용하려고 합니다.
- SpinLock이란 다른 스레드가 lock을 소유하고 있을 경우, 컨텍스트 스위칭을 하지 않고 그 lock이 반환될 때 까지 계속 Spin(루프)를 돌면서 재시도하는 것을 의미합니다.
- 자세한 내용은 http://itnovice1.blogspot.com/2019/09/spin-lock.html 를 참고합시다.
LocalRedis 실행 설정
- 스프링 부트가 기동하면서 Bean 등록할 때 레디스를 실행하고, 종료되면 Bean을 삭제할 때 레디스를 종료하도록 설정
- 해당 Bean이 Redis Repository보다 빨리 실행될 수 있도록 패키지 순서를 위쪽으로 해야합니다.
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import redis.embedded.RedisServer;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Configuration
public class LocalRedisConfig {
@Value("${spring.redis.port}")
private int redisPort;
private RedisServer redisServer;
@PostConstruct
public void startRedis() {
redisServer = new RedisServer(redisPort);
redisServer.start();
}
@PreDestroy
public void stopRedis() {
if (redisServer != null) {
redisServer.stop();
}
}
}
Redis Repository 등록 (Redisson Client 생성)
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RedisRepositoryConfig {
@Value("${spring.redis.host}")
private String redisHost;
@Value("${spring.redis.port}")
private int redisPort;
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
config.useSingleServer().setAddress("redis://" + redisHost + ":" + redisPort);
return Redisson.create(config);
}
}
Application.yml
spring:
datasource:
url: jdbc:h2:mem:test
username: sa
password:
driver-class-name: org.h2.Driver
h2:
console:
enabled: true
jpa:
defer-datasource-initialization: true
database-platform: H2
hibernate:
ddl-auto: create-drop
open-in-view: false
properties:
hibernate:
format_sql: true
show_sql: true
jdbc:
batch_size: 100
redis:
host: 127.0.0.1
port: 6379
RedisTestService
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Slf4j
@Service
@RequiredArgsConstructor
public class RedisTestService {
private final RedissonClient redissonClient;
public String getLock() {
// Lock 가져오기
RLock lock = redissonClient.getLock("sampleLock");
try {
// lock이 사용중이면 1초 동안 Lock을 기다리고 lock을 얻으면 5초 동안 Lock을 가지고 있다가 해제
// 명시적으로 unlock을 안하면 5초동안 가지고 있습니다.
boolean isLock = lock.tryLock(1, 5, TimeUnit.SECONDS);
if (!isLock) {
log.error("================== Lock acquisition failed =================");
return "Lock failed";
}
} catch (Exception e) {
log.error("Redis lock failed");
}
return "Lock Success";
}
}
TestController
private final RedisTestService redisTestService;
@GetMapping("/get-lock")
public String getLock() {
return redisTestService.getLock();
}
실행 결과
// 처음 시도 시
// 5초간 해당 Lock 잠김
get lock success
// 5초안에 다시 시도할 경우
// 1초동안 Lock이 풀릴 때까지 기다리다 시간이 초과되면 메세지 출력됌
Lock failed
출처
https://velog.io/@rlaghwns1995/Redis-%EA%B8%B0%EB%B3%B8%EC%A0%95%EB%A6%AC
'Spring Framework > Spring Boot' 카테고리의 다른 글
커스텀 properties 등록하기 (0) | 2022.06.08 |
---|
댓글