처음에는 스프링에서 Redis를 어떻게 활용하는지 알아보려 했습니다. 하지만 이 주제가 특정 언어와 프레임워크에 너무 국한될 것 같아 다른 주제로 방향을 바꾸게 되었습니다.
Redis pipeline
Redis Pipeline이란 Redis의 명령어들을 일괄로 처리하여 RTT(Round - Trip - Time)를 최적화 하는 방법입니다.
일괄로 처리하는 것과 개별로 처리하는 것을 GET, MGET에 비교해 설명하겠습니다.
여러 키를 조회할 때 GET으로 조회를 하게 되면 조회를 할 때마다 RTT가 발생합니다.
하지만 MGET은 한 번의 작업으로 충분해 RTT를 절약할 수 있습니다.
RTT (Round Trip Time)이란?
네트워크 요청을 시작한 후 응답을 받는데 걸리는 시간을 의미합니다.
쉽게 왕복시간이라고 생각하시면 됩니다.
파이프라인은 MGET과 같이 여러 명령어를 한꺼번에 처리할 수 있는 방법입니다.
그러므로 RTT를 줄일 수 있습니다.
또한 파이프라이닝은 컨텍스트 스위칭을 줄여 지연 시간 문제를 해결하는데에도 유용합니다.
파이프라이닝은을 사용하지 않았을 때는 각 명령을 처리하는 데 필요한 데이터 구조 접근과 응답 생성 비용은 적지만, 소켓 I/O 비용은 큽니다.
소켓 I/O 작업은 read(), write() 시스템 호출로 이루어지며, 이는 사용자 영역에서 커널 영역으로 전환을 의미합니다.
이 전환은 컨텍스트 스위칭이라 불리며, 상당한 속도 저하를 초래합니다.
사용자 영역이란?
프로그램이 동작하기 위해 사용되는 메모리 공간 (코드 영역, 스택 영역, 힙 영역)
커널 영역이란?
메모리에서 사용자 영역을 제외한 영역이다.
*커널이란 자원에 접근하고, 프로그램이 안전하게 실행되게 담당하는 부분입니다. (사람의 심장)
컨텍스트 스위칭이란?
운영 체제가 다른 작업을 수행하기 위해 CPU의 컨텍스트를 저장하고 복원하는 과정입니다.
하지만 파이프라이닝을 사용하면 많은 명령이 단일 read() 시스템 호출로 읽히고, 여러 응답이 단일 write() 시스템 호출로 전달됩니다.
결과적으로 컨텍스트 스위칭이 적게 일어나며 이로 인해 더 많은 쿼리를 처리할 수 있습니다.
하지만 파이프 라인은 조건 분기등을 적용할 수 없어 복잡한 로직에는 적합하지 않습니다.
또한 한 번에 응답을 반환하기 때문에 읽기 명령과 쓰기 명령이 포함되는 경우에는 읽기 명령의 결과를 기다려야 하므로 지연 시간이 길어질 수 있습니다.
파이프라인은 명령의 순서가 보장되기 때문에 읽기 명령이 먼저 있는 경우 결과가 반환될 때까지 대기해야 합니다.
트랜잭션 vs 파이프라인
Redis의 MULTI / EXEC 트랜잭션에서도 파이프라인은 사용됩니다.
EXEC 명령 이후에 한 번에 결과가 반환됩니다. -> 파이프라인의 특징
Redis는 싱글 스레드로 동작하기 때문에 개별 명령어는 항상 원자적으로 실행됩니다.
즉, 하나의 명령어는 중간에 다른 명령어가 끼어들지 않고 완전히 실행됩니다.
그러나 다른 클라이언트로부터 들어온 두 개의 명령어는 서로 번갈아가며 실행될 수 있습니다.
하지만 Redis의 트랜잭션을 사용하면 해당 블록 내의 명령어들이 실행되는 동안 다른 클라이언트의 명령어가 중간에 끼어들지 않도록 보장됩니다. 즉, MULTI와 EXEC 사이에 있는 모든 명령어들은 하나의 원자적 단위로 실행되며, 다른 클라이언트의 명령은 실행되지 않습니다.
https://stackoverflow.com/questions/29327544/pipelining-vs-transaction-in-redis
다른 클라이언트의 명령을 실행?
Redis는 싱글스레드로써 하나의 명령이 실행될 때 다른 명령이 실행되지 않는 격리성을 가지고 있습니다.
하지만 트랜잭션의 관점으로 접근했을 때 Redis는 격리성을 가지고 있지 않습니다.
그 이유로는 Redis의 트랜잭션이 실행됐을 때(MULTI를 선언한 후) 다른 클라이언트의 명령은 실행될 수 있습니다.
이는 MULTI 명령이 다른 클라이언트의 명령 실행을 차단하지 않기 때문입니다.
https://solution-is-here.tistory.com/216#Redis%EC%9D%98%20ACID-1
그리고 EXEC를 통해 트랜잭션을 종료시켰을 때 큐에 있는 명령이 중간에 다른 클라이언트의 명령 없이 연속적으로 실행됩니다.
이러한 특징으로 원자성을 보장하는 것입니다.
Redis Module
RedisModule이란 레디스 소스코드를 수정하지 않고도 C 언어로 구현하여 Redis 서버에 독립적으로 추가할 수 있는 기능입니다.
Redis Module을 통해 사용자가 새롭게 정의한 자료형을 추가할 수 있습니다.
대표적으로 밑의 4가지가 있습니다.
일부 자료형의 경우 마지막 Release가 몇 년전입니다.
메인테이너, 커미터가 프로젝트를 잘 관리하는지 살펴보고 사용하시는 것을 추천드립니다.
(관리하지 않는 경우, 버그가 발생해도 고칠 수 없는 경우가 생길 수 있음)
RedisJSON
Github Star 제일 많은 RedisJSON에 대해 설명하겠습니다.
우선 알다시피, Redis의 String 자료형은 이진 안전 문자열입니다. 그러므로 JSON도 저장할 수 있습니다.
이때 RedisJSON과 String에 JSON을 저장하는 것에 차이가 있습니다.
Store JSON in Redis String vs RedisJSON
Redis 문자열 자료형에 JSON을 저장하는 것은 단순히 문자열을 저장하는 것과 같습니다.
JSON 값 중, 특정 요소만 읽어와야 하는 상황에서도 JSON 문자열 전체를 가져오며, 수정이 필요한 경우 애플리케이션 단에서 역 직렬화를 통해 객체로 변환한 뒤, 변경하고 직렬화 하고 저장을 합니다.
이처럼, JSON을 문자열 자료형에 저장하면 저장, 조회만 가능하다는 것을 알 수 있습니다.
그에비해 RedisJSON 모듈은 JSON 값 중, 특정 요소만 변경할 수 있습니다.
예를 들어 isDeleted라는 필드를 False에서 True로 변경한다고 가정해보겠습니다.
Redis 문자열 자료형에서는 역직렬화, 직렬화를 통해 애플리케이션 단에서 처리를 하는 반면, RedisJSON 모듈은 명령을 통해 특정 필드의 값을 변경할 수 있습니다.
isDelete라는 간단한 예시를 들었지만, 원자적 처리가 필요한 값(e.g 점수, 잔고)으로 넘어가게 되면 Redis 문자열 자료형에서는 따로 트랜잭션 처리를 해야 합니다. 만약 다른 클라이언트가 문서에 접근한 경우, 트랜잭션이 실패하므로 모든 단계를 다시 시도해야 할 수도 있습니다.
https://stackoverflow.com/questions/78757857/redisjson-vs-jackson-objectmapper
RedisJSON
redis.cloud:6379> SET myDoc '{"colors": ["green"]}'
OK
redis.cloud:6379> JSON.ARRAPPEND myDoc colors '"blue"'
(integer) 2
위 코드와 같이 RedisJson을 사용하면 JSON 배열에 요소를 추가하는 등 명령어를 통해 JSON을 편하게 사용할 수 있습니다.
RedisJSON Command
1. JSON.ARRAPPEND / O(1)
경로에 있는 Json 배열의 마지막 요소 뒤에 값을 추가합니다.
2. JSON.SET / O(M + N)
1. 새로운 RedisJSON 키에 값 추가하기
user라는 키가 없는 경우 키가 생성되고, name과 age가 루트에 저장됩니다.
루트란 JSONPath에서 최상위 경로를 의미합니다.
JSON.SET user $ '{"name": "Alice", "age": 30}'
2. 루트 경로의 값을 업데이트 하기
이미 user라는 키가 존재하고, name과 age가 존재할 때 경로 ($.age)가 동일하다면 age 값이 변경됩니다.
JSON.SET user $.age 26
3. 경로에 새로운 자식 추가하기
키가 동일하고 경로가 존재하지 않는 경우 새로운 필드를 추가할 수 있습니다.
JSON.SET user $.email '"bob@example.com"'
3. JSON.GET / O(N)
경로에 있는 Json 배열을 직렬화 한 형태로 값을 반환합니다.
그 외의 명령어는 밑의 링크를 보시면 됩니다.
https://redis.io/docs/latest/operate/oss_and_stack/stack-with-enterprise/json/commands/
Redis의 미래
https://survey.stackoverflow.co/2024
Stackoverflow 2024년 개발자 설문조사 결과입니다.
그 중, Databases 설문조사 결과를 보았는데 매우 흥미로운 결과가 나왔습니다.
Which database environments have you done extensive development work in over the past year, and which do you want to work in over the next year? (If you both worked with the database and want to continue to do so, please check both boxes in that row.)
지난 1년 동안 광범위한 개발 작업을 수행한 데이터베이스 환경은 무엇이며, 앞으로 1년동안 작업할 데이터베이스 환경은 무엇입니까?
(데이터베이스 작업을 수행 했고, 앞으로도 수행하고 싶다면 해당 행의 두 상자를 모두 선택하십시오)
즉 쉽게 말해 사용했던 데이터베이스와 사용할 데이터베이스를 모두 고르라는 질문이다.
전 세계에 있는 수 많은 개발자들 중, 52,418명의 개발자 분께서 Databases 관련 응답에 선택을 했습니다.
이때 20%의 개발자가 Redis를 사용했고 사용할 예정이어서 선택을 했습니다.
하지만 설문 조사를 조금 더 자세히 보면 흥미로운 점이 있습니다.
위 결과는 Learning to Code, 코딩을 배우고 있는 사람들이 선택한 결과입니다.
코딩을 배우고 있는 사람들 중, 6.9%의 개발자만이 Redis를 사용했고, 사용할 계획이라고 했습니다.
5,093명의 개발자가 설문을 한 결과입니다.
위 결과는 Professional Developers, 전문 개발자 분들이 선택한 결과입니다.
전문 개발자분들 중, 22.8%의 개발자가 Redis를 사용했고 사용할 예정이라고 했습니다.
41,000명의 개발자가 설문을 한 결과입니다.
이는 코딩을 배우고 있는 사람들의 수치의 3배에 달하며, Redis라는 데이터베이스는 코딩을 배우는 개발자 보단, 전문 개발자분들이 많이 사용하는 것을 알 수 있습니다.
Stackoverflow와 같은 사이트의 특성상 백엔드 개발자만 설문에 참여하는 것이 아니기 때문에, 백엔드 개발자만을 고려했을 때 수치가 더 높을 것으로 예상됩니다.
Redis의 핑크빛 미래?
이렇게만 본다면 Redis는 개발자들이 선호하는 데이터베이스 Top 10안에 계속 남을 수 있을 것처럼 보이지만, Redis에는 라이센스 변경과 같은 악재가 존재합니다. 이로 인해 수 많은 fork 프로젝트가 생성이 되었고 주시해야 할 필요성이 있습니다.
밑의 그림은 Valkey 및 Redis 오픈 소스용 클라이언트 라이브러리 Valkey GLIDE입니다.
Valkey GLIDE는 각 언어별 래퍼를 통해 언어와 호환성을 제공하며, Valkey, Redis OSS와 통신을 담당하는 코어 로직이 있으며 통신 계층을 통해 코어와 래퍼간의 응답과 요청을 전송합니다.
Valkey, Redis OSS뿐만 아니라 AWS Elasticache, AWS MemoryDB와도 함께 사용할 수 있습니다.
또한 Valkey GLIDE의 pub/sub 채널은 상태 저장입니다.
연결이 끊어지거나 확장, 축소와 같은 토폴로지 업데이트가 발생하는 경우 GLIDE는 자동으로 새 노드에 대한 연결을 다시 구독합니다.
이는 연결이 끊어졌을 때 수동으로 다시 구독을 설정해야 하는 Redis OSS와 차이가 있습니다.
Valkey GLIDE는 AWS의 후원과 지원을 받습니다. GLIDE는 모든 Valkey 및 Redis OSS 명령을 지원하고 안정성을 위해 설계되었으며 모범 운영 사례를 기반으로 사전 구성되었습니다.
Redis의 라이센스 변경에는 AWS와 같은 클라우드 업체가 Redis에 투자를 하지 않고 상업적인 이윤을 얻는다는 이유가 있었는데 라이센스 변경을 한 이후에는 Redis가 아닌 fork 프로젝트인 valkey에 투자를 하는 모습이 흥미로웠습니다.
Redis와 Valkey를 모두 지원하는 라이브러리인 Valkey-GLIDE에 대한 글입니다.
Valkey는 정말 무서울 정도로 빠르게 발전하고 있습니다.
제가 생각하는 개발자란 항상 흐름을 놓치지 말아야 하는 사람입니다.
AWS가 Valkey에 직접적으로 지원을 한 이상, 생각보다 Valkey가 Redis를 빠르게 대체할 수도 있겠다라는 생각이 듭니다.
추후에 Valkey 프로젝트에 큰 변화가 생긴다면 Valkey 프로젝트 소개 글로 찾아 뵙겠습니다.
결론은 계속 공부하자....
Continuous learning :-)