DBMS
(Spring) Lettuce를 활용하여 Redis를 활용하는 방법을 알아보자
너어디사니
2024. 7. 9. 21:36
Spring 에서 Redis를 다루기 위해서는 다양한 라이브러리들이 있는데 나는 그중에서 Lettuce를 활용한 Redis 구현을 해보려고 한다
여기서 잠깐 Redis란??
- Redis는 Key - Value 값을 기반으로 하는 In Memory NOSQL DB 이다
장점
- 모든 데이터를 메모리에 저장하기 때문에 속도가 굉장히 빠르다
- 다양한 자료구조를 저장하기 때문에 보다 다양하게 데이터를 관리 할 수 있다
- 만료 시간을 설정할 수 있고 만료 시간이 지나면 자동으로 지워지기 때문에 보다 효율적인 데이터 관리가 가능하다
단점
- 용량이 작기 때문에 대용량으로 저장하기 어렵다
- 휘발성이 있기 때문에 일반 DB와 같이 사용 하는 것이 좋다
- 싱글 스레드 이기 때문에 하나의 명령어만 처리가 가능하다 즉 크기가 큰 명령을 처리하게 될 경우 성능이 저하 될 수 있다
Redis의 자료구조
- String : 문자열 데이터를 저장 및 조회할 수 있는 Key - Value 기반의 기본 자료 구조
- Bitmap : 비트 단위로 데이터를 저장하고 조작할 수 있는 자료구조, 사실상 위의 자료구조와 비슷하다
- List : 양방향 Linked List 형태로 서로 연결되어 있는 자료 구조 , 양 끝에서 데이터를 빼오거나 삽입하는게 가능하다
- Hashe : hash 값과 fileld - Value 로 구성된다. 하나의 hash 안에서 여러개의 field - value를 저장할 수 있기 때문에 사용자의 데이터를 저장하는데 용이하다
- Set : 중복을 허용하지 않는 List와 비슷한 자료 구조
- Sorted Set(ZSet) : Set과 비슷한 집합 데이터로 정렬 기능을 제공한다. 점수와 값의 쌍으로 저장이 된다 Sorted Set은 점수 값을 사용하여 정렬하고, 점수 값이 중복되면 사전 순으로 정렬한다.
- Hypperloglog : 대량의 고유 항목 수를 메모리 효율적으로 추정하는 데 사용 하는 자료구조이다
- Stream : 레디스 5.0 버전부터 제공하는 기능, 로그 및 메시징 시스템에 적합한 고유한 ID가 있는 데이터 스트림.
Lettuce 초기 셋팅
1. application.yml 과 build.gradle.kts 에 셋팅을 해준다
#appcation.yml
spring:
data:
redis:
host: localhost
port: 6379
//build.gradle.kts
implementation("io.lettuce:lettuce-core:6.3.2.RELEASE")
2. Lettuce 환경 구성
- redis를 설치해준다
brew install redis
- Class에 기본 설정을 구성해준다
@Configuration
class LettuceRedis(
){
private val redisClient = RedisClient.create("redis://localhost:6379") // 여기서 Redis 주소를 지정
private val connection: StatefulRedisConnection<String, String> = redisClient.connect() // Redis 주소 연결
private val command = connection.sync() // Redis 싱크 후 사용
3. 이 후 사용하면 끝
- 환경 설정이 까다로운 RedisTemplete과는 달리 환경설정이 굉장히 간편하다는 장점이 있다
4. 각 자료구조 별 입출력 메서드
- String
commands.set("key", "value") //Set 메서드로 String 자료구조 저장
commands.get("key") //Get 메서드로 String 자료구조 저장
commands.incr("count") // incr 메서드로 키의 값을 1만큼 증가
commands.decr("count") // decr 메서드로 키의 값을 1만큼 감소
- Bitmap
// bitmap에서 특정 위치에 비트맵을 설정 true는 특정 비트를 1 false는 0으로 설정
commands.setbit("Key", 10, true)
// bitmap에서 특정 위치의 비트를 가져온다
commands.getbit("bitmapKey", 10)
// bitmap에서 1로 설정된 비트의 수를 계산
commands.bitcount("bitmapKey")
- List
// List 왼쪽에 값을 추가
commands.lpush("Key", "value1")
// List 오른쪽에 값을 추가
commands.rpush("Key", "value2")
// List 왼쪽에 값을 가져오고 제거
commands.lpop("Key")
// List 오른쪽에 값을 가져오고 제거
commands.rpop("Key")
// List 특정 범위의 값을 가져온다
commands.lrange("Key", 0, -1)
// List 길이를 가져온다
commands.llen("Key")
- Hash
//hash field에 값을 설정한다
commands.hset("Key", "field", "value")
//hash field에 맞는 값을 가져온다
commands.hget("Key", "field")
//hash에 맞는 값을 모두 가져온다
commands.hgetall("Key")
//hash field를 삭제한다
commands.hdel("Key", "field")
//hash field의 수를 가져온다
commands.hlen("Key")
- Set
// Set에 값을 추가
commands.sadd("key", "value1")
// Set에 값을 제거
commands.srem("key", "value1")
// Set에 모든 값을 가져온다
commands.smembers("key")
// Set에 값이 존재하는지 확인
commands.sismember("key", "value1")
- Sorted Set
// 정렬된 Set에 점수와 함께 값을 추가
commands.zadd("Key", 1.0, "value1")
// 정렬된 Set에 특정 범위의 값을 가져온다
commands.zrange("Key", 0, -1)
// 정렬된 Set에 값의 순위를 가져온다
commands.zrank("Key", "value1")
// 정렬된 Set에서 값을 제거
commands.zrem("Key", "value1")
// 정렬된 Set에서 값의 점수를 가져온다
commands.zscore("Key", "value1")
- Hypperloglog
// HyperLogLog에 값을 추가
commands.pfadd("Key", "value1", "value2")
// HyperLogLog의 고유 항목 수를 계산한다
val uniqueCount: Long = commands.pfcount("Key")
// 여러 HyperLogLog를 병합
commands.pfmerge("MergedKey", "Key1", "Key2")
- Stream
// Stream 에 새 항목을 추가
commands.xadd("Key", mapOf("id" to "1234", "temperature" to "19.8"))
// Stream 에 항목을 가져온다
commands.xread(XReadArgs.StreamOffset.from("Key", "0"))
// Stream 그룹을 관리한다
commands.xgroupCreate(StreamOffset.from("Key", "0"), "groupName")
// Stream 메시지를 확인한다
commands.xack("Key", "groupName", "messageId")
5. RedisEviction
- Redis가 사용하는 메모리가 maxMemory 에 지정한 크기보다 커지면 Redis는 사용자가 지정한 Eviction 정책에 따라 저장되어 있는 데이터를 제거한 후, 새로운 데이터를 저장하게 되는데 이 때 사용할 수 있는 방법이다
- RedisEviction 정책은 아래와 같으며 필자는 ENUM 타입으로 해당 정책을 상수화 해서 관리하고 있다
NO_EVICTION("noeviction"), //메모리 부족 시 새로운 키를 추가하려는 작업이 실패한다
ALL_KEYS_LRU("allkeys-lru"), //사용 빈도가 낮은 모든 키를 제거한다
VOLATILE_LRU("volatile-lru"), //사용 빈도가 낮은 만료 키를 제거한다
ALL_KEYS_RANDOM("allkeys-random"), //임의의 모든 키를 제거한다
VOLATILE_RANDOM("volatile-random"), //임의의 만료 키를 제거한다
VOLATILE_TTL("volatile-ttl") //만료 시간이 짧은 키를 제거한다
- RedisEviction 정책 사용 방법
- init 블록에서 사용하는 방법과 메서드 내부에서 사용하는 방법이 있는데 전체적인 Redis 정책을 설정해주는 것과 세부적인 Redis 정책을 설정하는 차이점이 있으니 프로젝트에 맞춰서 사용하면 될 것 같다
init {
command.configSet("maxmemory-policy", RedisEviction.VOLATILE_TTL.policy)
}