반응형
1. Redis란?
Remote Dictionary Server의 약자로 키-값 구조의 비관계형 데이터베이스 시스템 (NoSql의 한 종류)
Redis는 인메모리 DB 특성상 데이터를 영속화 하지 않으면 사라지는 특성을 가지고 있다
그리고 빠른 성능과 제한된 용량으로 보통 자주 읽는 데이터를 캐싱하는데 자주 사용된다
2. Redis 구성 방법
Redis를 구성하는 방법에는 Cluster, Sentinel 두 가지 방법이 존재한다
1) Sentinel
Sentinel 방식은 말 그대로 보초로서 Redis서버(Master, Replica)에 대한 모니터링을 수행하고 장애가 발생했을 때 Failover를 수행함으로서 가용성을 보장하는 구성이다
Sentinel의 역할
- 모니터링/장애 조치
1) Redis서버에 지속적으로 Ping을 보내어 Redis서버가 alive 상태인지 확인
2) Redis서버에 장애가 발생하는 경우 Sentinel이 이를 감지하고 다른 센티넬들에게 이를 공유하고 정족수(quorum)이상의 Sentinel들이 down으로 판단한 경우 실질적 down으로 판단
3) 리더 Sentinel이 선출되고 리더 Sentinel에 의해 장애 Redis서버에 대해 Failover 수행(단, Master에 대해서만 Failover 수행하며 Replica에 대해서는 Failover 수행하지 않음) - 구성 정보 제공
Sentinel은 Redis 노드를 감시하고 마스터 노드에 대한 정보를 제공하는 역할을 한다
Sentinel로 구성된 Redis르 Client가 연결할 때는 Sentinel을 통해 구성 정보를 받아야 한다(Failover가 발생했을 때 Master가 변경되기 때문)
- Sentinel구성은 Sentinel이 장애가 발생하여 quorum(정족수)를 미달하는 경우 Failover가 정상적으로 이루어지지 않을 수 있기 때문에 Sentinel에 대한 모니터링이 중요하다
2) Cluster
Cluster 방식은 확장성 및 고가용성을 갖춘 방식으로 데이터를 분산(Sharding)하고 자동으로 Failover를 지원하는 방식이다
- 데이터 분산
16384개의 Hash Slot으로 분할된 키를 각 마스터가 담당하여 처리한다 - 장애조치
Master 별로 1개 이상의 Replica를 가지고 Master가 장애로 감지되면 Replica중 하나가 Master로 승격된다
이때, Cluster 내 다수의 노드가 동의 하는 경우 장애로 간주 된다(quorum 기준 이상) - 노드 간 통신
Cluster 노드 간에는 gossip protocol로 서로 통신하고 주기적으로 상태 정보를 교환 한다
이를 통해 각 노드는 Cluster 내 다른 노드 정보를 알고 있다
- 노드별로 슬롯을 담당하고 있는 형태인 Cluster는 노드가 추가되는 경우 리벨런싱 작업이 필요하고 이는 자동으로 이루어지지 않는다
3. Spring에서 Redis 사용
의존성
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-redis")
}
이때 기본 Redis 클라이언트는 Lettuce 이다
yaml 설정
1. Sentinel
spring:
redis:
sentinel:
master: master (master 이름)
nodes:
- 127.0.0.1:26379
- 127.0.0.1:26380
- 127.0.0.1:26381
password: password (패스워드 설정한 경우 입력)
2. Cluster
spring:
redis:
cluster:
nodes:
- 127.0.0.1:7000
- 127.0.0.1:7001
- 127.0.0.1:7002
password: password (패스워드 설정한 경우 입력)
Spring에서 활용
@Configuration
class RedisConfig {
@Bean
fun redisTemplate(connectionFactory: RedisConnectionFactory): RedisTemplate<String, Any> {
val template = RedisTemplate<String, Any>()
template.setConnectionFactory(connectionFactory)
template.keySerializer = StringRedisSerializer()
template.valueSerializer = GenericJackson2JsonRedisSerializer()
return template
}
}
Redis Config 클래스의 경우 Custom이 필요한 경우 생성하면 되고 기본적으로도 redisTemplate에 대한 Bean이 생성 된다
@RestController
@RequestMapping("/redis")
class RedisController(
private val redisService: RedisService
) {
@PostMapping("/set")
fun setValue(@RequestParam key: String, @RequestParam value: String): ResponseEntity<String> {
redisService.addValue(key, value)
return ResponseEntity.ok()
}
@GetMapping("/get")
fun getValue(@RequestParam key: String): ResponseEntity<Any?> {
return ResponseEntity.ok(redisService.findValueByKey(key))
}
}
@Service
class RedisService(
private val redisTemplate: RedisTemplate<String, Any>
) {
fun addValue(key: String, value: Any, ttlSec: Long = 3600) {
redisTemplate.opsForValue().set(key, value, Duration.ofSeconds(ttlMinutes))
}
fun findValueByKey(key: String): Any? {
return redisTemplate.opsForValue().get(key)
}
fun deleteByKey(key: String) {
redisTemplate.delete(key)
}
}
위 코드는 예제 코드로 실무에서 활용시에는 Redis를 직접 서비스에서 사용하기 보다는 별도의 Redis 전용 Repository나 인터페이스를 만들고 용도별로 구현체를 분리하는 방식이 유지보수나 활용 측면에서 더 효율적이다
반응형
'공부' 카테고리의 다른 글
Kotlin 기본 문법 정리 - 함수 (0) | 2025.07.18 |
---|---|
Kotlin 기본 문법 정리 - 타입과 변수 (0) | 2025.07.17 |
Gradle 개념과 역할 (0) | 2025.07.15 |
[DB] S/X Lock (0) | 2025.06.24 |
레거시 시스템에서 발생하는 DeadLock에 대한 고찰 (0) | 2025.06.18 |