Redis 8.0 주요 변경점 — I-O 스레딩, Vector Search, 클러스터 쿼리
Redis는 오랫동안 '빠르지만 단순한 캐시'라는 이미지였습니다. 그런데 8.0에서는 벡터 검색, I/O 스레딩, 클러스터 쿼리까지 탑재했는데 — 어디까지 변한 걸까요?
개념 정의 — Redis 8.0 한 줄 요약
Redis 8.0은 **I/O 스레딩 기본 활성화 **, ** 벡터 검색 코어 내장 **, ** 공유 복제 버퍼 , ** 클러스터 쿼리 개선 등을 통해 성능과 기능 범위 모두를 대폭 확장한 메이저 릴리스입니다. 기존 Redis Stack의 모듈(RediSearch, RedisJSON, RedisTimeSeries 등)이 코어로 통합되면서, 별도 모듈 설치 없이 사용할 수 있게 되었습니다.
Redis 버전 히스토리 간략
8.0의 변경점을 이해하려면 이전 버전에서 어떤 흐름이 있었는지 가볍게 짚고 넘어가는 게 좋습니다.
| 버전 | 핵심 변경점 |
|---|---|
| 6.0 (2020) | ACL(접근 제어 리스트), I/O 스레딩 옵트인(기본 비활성), SSL/TLS 지원 |
| 6.2 (2021) | GETDEL, COPY, CLIENT NO-EVICT 등 명령 추가 |
| 7.0 (2022) | Redis Functions(Lua 대체), Sharded Pub/Sub, AOF 다중 파트, listpack 일부 적용 |
| 7.2 (2023) | 클라이언트 사이드 캐싱 개선, 자동 페일오버 속도 향상 |
| 8.0 (2025) | I/O 스레딩 기본 활성, 모듈 코어 통합(벡터 검색, JSON 등), 공유 복제 버퍼, 라이선스 변경 |
흐름을 보면 Redis가 "단순한 캐시"에서 "다기능 데이터 플랫폼"으로 방향을 잡아온 것이 보입니다. 8.0은 그 방향의 결정판이라고 할 수 있습니다.
I/O 스레딩 기본 활성화
이전: 옵트인 방식의 I/O 스레딩
Redis 6.0에서 io-threads 설정이 추가되었지만, 기본값은 1(비활성)이었습니다. 그리고 io-threads-do-reads를 별도로 켜지 않으면 쓰기만 스레딩되었습니다. 실무에서 이 설정을 켜고 운영하는 팀은 의외로 많지 않았습니다.
# Redis 6.0~7.x (기본 비활성, 수동 설정 필요)
io-threads 1 # 기본값: 사실상 비활성
io-threads-do-reads no # 읽기는 스레딩 안 함
8.0: 읽기 + 쓰기 모두 기본 스레딩
8.0에서는 I/O 스레딩이 ** 기본 활성화 **되었습니다. 읽기와 쓰기 모두 여러 스레드에서 처리하며, Redis가 시작 시 CPU 코어 수를 감지해서 적절한 스레드 수를 자동으로 설정합니다.
# Redis 8.0 (기본 활성, 자동 감지)
io-threads auto # CPU 코어 수 기반 자동 설정
# 읽기+쓰기 모두 스레딩 (별도 설정 불필요)
벤치마크 결과
공식 벤치마크에 따르면 I/O 스레딩만으로 throughput이 최대 112% 향상 되었습니다. 특히 GET/SET 같은 단순 명령에서 효과가 극대화됩니다. 네트워크 I/O가 병목인 환경(클라이언트 수천 개 이상)에서 체감 효과가 큽니다.
여전히 싱글 스레드인 것
공부하다 보면 "I/O 스레딩 = 멀티스레드 Redis"로 오해하기 쉬운데, 핵심은 이것입니다.
명령 실행(데이터 접근)은 여전히 싱글 스레드입니다. 락이 필요 없는 실행 모델이 유지되므로 데이터 안전성은 그대로입니다. 바뀐 것은 네트워크 소켓 읽기/쓰기를 여러 스레드가 분담하는 것뿐입니다.
처리 흐름을 그림으로 보면 이렇습니다.
┌─────────┐ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐ ┌─────────┐
│ Client │───→│ I/O Thread │───→│ Main Thread │───→│ I/O Thread │───→│ Client │
│ 요청 │ │ (소켓 읽기) │ │ (명령 실행) │ │ (소켓 쓰기) │ │ 응답 │
└─────────┘ └──────────────┘ └─────────────┘ └──────────────┘ └─────────┘
↑ 병렬 처리 ↑ 싱글 스레드 ↑ 병렬 처리
(여러 스레드) (락 불필요) (여러 스레드)
내장 벡터 검색 (Vector Search)
모듈에서 코어로
이전에는 벡터 검색을 사용하려면 **RediSearch 모듈 **(Redis Stack의 일부)을 별도로 설치해야 했습니다. 운영 환경에서 모듈 관리가 번거로웠고, AWS ElastiCache 같은 매니지드 서비스에서는 지원하지 않는 경우도 있었습니다.
Redis 8.0에서는 RediSearch, RedisJSON, RedisTimeSeries, RedisBloom, RedisGraph 등 주요 모듈이 ** 코어에 통합 **되었습니다. 별도 모듈 설치 없이 바로 벡터 검색을 쓸 수 있습니다.
벡터 인덱스 생성과 검색
벡터 검색의 기본 흐름은 "인덱스 생성 → 데이터 저장 → KNN 검색"입니다.
# 1. 벡터 인덱스 생성 (HNSW 알고리즘, 384차원)
FT.CREATE product_idx ON HASH PREFIX 1 product: \
SCHEMA \
name TEXT \
category TAG \
embedding VECTOR HNSW 6 \
TYPE FLOAT32 \
DIM 384 \
DISTANCE_METRIC COSINE
# 2. 데이터 저장 (임베딩 벡터 포함)
HSET product:1 name "무선 이어폰" category "전자기기" \
embedding "\x00\x00\x80\x3f..." # 384차원 float32 바이너리
# 3. KNN 검색 — 가장 유사한 5개 상품 조회
FT.SEARCH product_idx \
"*=>[KNN 5 @embedding $query_vec AS score]" \
PARAMS 2 query_vec "\x00\x00\x80\x3f..." \
SORTBY score ASC \
RETURN 2 name score
인덱스 타입: HNSW vs FLAT
| HNSW | FLAT | |
|---|---|---|
| 검색 속도 | O(log N) — 빠름 | O(N) — 느림 |
| ** 정확도** | 근사치 (Approximate) | 정확 (Exact) |
| ** 메모리** | 그래프 인덱스 추가 메모리 필요 | 벡터 데이터만 저장 |
| ** 적합 시나리오** | 대규모 (수십만~수백만 벡터) | 소규모 (수천 벡터 이하) |
대부분의 프로덕션 환경에서는 HNSW 를 사용합니다. 소규모 데이터에서 정확한 결과가 필요하면 FLAT을 선택하면 됩니다.
AI/ML 시대의 Redis
LLM 애플리케이션에서 임베딩 벡터를 Redis에 캐싱하고 검색하는 패턴이 늘어나고 있습니다. 기존에는 Pinecone, Milvus 같은 전용 벡터 DB를 따로 운영해야 했는데, Redis 하나로 캐시 + 벡터 검색을 동시에 처리할 수 있게 된 것이 큰 변화입니다.
이미 Redis를 캐시로 쓰고 있는 환경이라면, 별도 벡터 DB를 도입하는 대신 Redis 8.0의 내장 벡터 검색을 먼저 검토해보는 것이 합리적입니다. 운영 복잡도를 크게 줄일 수 있습니다.
클러스터 쿼리 개선
기존의 클러스터 제약
Redis Cluster는 16,384개의 해시 슬롯에 키를 분산합니다. 기존에는 서로 다른 슬롯에 있는 키를 한 번에 조회하는 것이 불가능 했습니다. 클라이언트가 MOVED나 ASK 리다이렉션을 직접 처리해야 했고, 멀티 키 명령(MGET, MSET 등)은 같은 슬롯의 키끼리만 사용할 수 있었습니다.
# 기존: 서로 다른 슬롯의 키 → 에러
MGET user:1 user:2 user:3
# (error) CROSSSLOT Keys in request don't hash to the same slot
8.0: Cross-slot 쿼리 지원 확대
Redis 8.0에서는 여러 슬롯에 걸친 읽기 쿼리 에 대한 제약이 완화되었습니다. 클러스터 모드에서도 FT.SEARCH 같은 검색 명령이 여러 샤드에 걸쳐 동작할 수 있습니다.
# Redis 8.0 클러스터: 여러 샤드에 걸친 검색 가능
FT.SEARCH my_index "@category:{electronics}" LIMIT 0 10
# → 모든 샤드에서 결과를 수집하여 반환
또한 FT.AGGREGATE 같은 집계 쿼리도 클러스터 환경에서 분산 실행됩니다. 각 샤드에서 부분 결과를 계산한 뒤, 코디네이터 노드에서 최종 결과를 합산하는 방식입니다.
다만
MGET,MSET같은 기본 멀티 키 명령은 여전히 같은 슬롯 제약이 있습니다. Cross-slot 개선은 주로 검색(FT.SEARCH)과 집계(FT.AGGREGATE) 쪽에 집중되어 있습니다.
복제 메모리 최적화
공유 복제 버퍼 (Shared Replication Buffer)
기존 Redis에서는 레플리카마다 독립적인 출력 버퍼 를 유지했습니다. 마스터가 쓰기 명령을 처리하면, 각 레플리카의 버퍼에 복제 데이터를 각각 복사 하는 구조였습니다.
# 기존: 레플리카별 독립 버퍼
Master ──→ [ Buffer for Replica 1 ] ──→ Replica 1
──→ [ Buffer for Replica 2 ] ──→ Replica 2
──→ [ Buffer for Replica 3 ] ──→ Replica 3
──→ [ Buffer for Replica 4 ] ──→ Replica 4
──→ [ Buffer for Replica 5 ] ──→ Replica 5
(같은 데이터가 5번 복사됨)
레플리카가 5대면 동일한 복제 데이터가 5배 메모리를 차지했습니다.
8.0: 공유 버퍼로 전환
Redis 8.0은 하나의 공유 복제 버퍼 에 복제 데이터를 기록하고, 각 레플리카가 이 버퍼를 참조하는 방식으로 바뀌었습니다.
# Redis 8.0: 공유 복제 버퍼
Master ──→ [ Shared Replication Buffer ] ←── Replica 1 (오프셋 읽기)
←── Replica 2 (오프셋 읽기)
←── Replica 3 (오프셋 읽기)
←── Replica 4 (오프셋 읽기)
←── Replica 5 (오프셋 읽기)
(데이터 1번만 저장, 레플리카는 오프셋으로 읽기)
각 레플리카는 공유 버퍼에서 자신의 읽기 오프셋만 관리합니다. 레플리카 5대 기준으로 복제 관련 메모리 사용량이 최대 80% 절감 됩니다.
대규모 클러스터를 운영하는 환경에서 이 개선은 상당히 의미가 큽니다. 레플리카가 많을수록 절감 효과가 커지니까요. 특히 읽기 부하 분산을 위해 레플리카를 많이 두는 서비스에서 체감됩니다.
기타 주요 변경점
listpack 전환 완료
Redis 7.0에서 시작된 ziplist → listpack 전환 이 8.0에서 완료되었습니다. Hash, Sorted Set, List 등의 소규모 인코딩이 모두 listpack으로 교체되었습니다.
- **ziplist 문제 **: 연쇄 업데이트(cascade update) — 중간 요소 크기가 바뀌면 뒤의 모든 요소를 이동해야 했음
- **listpack 장점 **: 연쇄 업데이트 없음, 메모리 레이아웃 개선, 약간 더 나은 메모리 효율
기존 RDB 파일의 ziplist 데이터는 로드 시 자동으로 listpack으로 변환되므로, 업그레이드 시 별도 마이그레이션은 필요 없습니다.
RESP3 기능 활용 확대
Redis 6.0에서 도입된 RESP3 프로토콜의 활용이 확대되었습니다. CLIENT NO-TOUCH, Push 알림 개선 등 RESP3 기반의 새로운 기능이 추가되었습니다.
TTL 관련 명령 개선
EXPIRETIME/PEXPIRETIME: 키의 만료 시각을 Unix 타임스탬프로 반환 (7.0에서 추가, 8.0에서 개선)- Hash 필드 단위 TTL 지원:
HEXPIRE,HPEXPIRE,HTTL등 — Hash의 개별 필드에 만료 시간을 설정할 수 있습니다
# Hash 필드별 TTL 설정
HSET session:user1 token "abc123" ip "192.168.1.1"
HEXPIRE session:user1 3600 FIELDS 1 token # token 필드만 1시간 후 만료
HTTL session:user1 FIELDS 1 token # 남은 TTL 확인
Hash 필드 단위 TTL은 세션 관리나 캐시에서 유용합니다. 기존에는 Hash 전체에만 TTL을 걸 수 있어서, 필드별로 다른 만료가 필요하면 별도 키로 분리해야 했습니다.
라이선스 변경 — RSALv2 + SSPLv1
Redis 8.0부터 라이선스가 기존 BSD에서 RSALv2(Redis Source Available License v2) + SSPLv1 듀얼 라이선스 로 변경되었습니다. 이 변경의 핵심은 클라우드 서비스 제공자가 Redis를 그대로 서비스로 제공하는 것을 제한 하는 것입니다.
이 라이선스 변경에 반발하여 Valkey 라는 포크가 탄생했습니다. Linux Foundation이 지원하며, AWS ElastiCache 등에서 Valkey를 채택하고 있습니다.
- **자체 서버에서 Redis 사용 **: 영향 없음
- ** 클라우드에서 Redis 매니지드 서비스 제공 **: 라이선스 제약 적용
- Valkey: BSD 라이선스를 유지하는 Redis 호환 포크
실무에서 Redis를 쓰는 대부분의 경우(자체 서버, 또는 AWS/Azure의 매니지드 서비스 이용)에는 큰 영향이 없습니다. 다만 Redis 기반 서비스를 직접 SaaS로 제공하는 경우라면 라이선스를 꼼꼼히 확인해야 합니다.
업그레이드 시 주의사항
호환성 체크포인트
- **RDB 호환성 **: Redis 8.0의 RDB 형식은 하위 호환됩니다. 다만 8.0에서 저장한 RDB를 이전 버전에서 로드하면 문제가 될 수 있습니다
- ** 모듈 명령 **: 기존 Redis Stack 모듈(RediSearch 등)의 명령은 그대로 사용 가능하지만, 일부 명령의 동작이 미세하게 달라질 수 있습니다
- ziplist → listpack: 자동 변환되지만, 대용량 데이터에서는 초기 로드 시간이 약간 증가할 수 있습니다
- ** 설정 파일 **:
io-threads관련 설정이 기본값이 변경되었으므로, 기존 설정 파일을 그대로 쓰면 의도하지 않은 동작이 있을 수 있습니다
라이선스 영향 범위 확인
업그레이드 전에 라이선스 변경이 조직에 미치는 영향을 반드시 확인해야 합니다. 특히 Redis를 기반으로 서비스를 제공하는 경우라면 법무팀 검토가 필요합니다.
모니터링 포인트
업그레이드 후 확인해야 할 메트릭들입니다.
info server: 버전 확인, I/O 스레드 수 확인info stats: ops/sec 변화 — I/O 스레딩 효과 확인info memory: 복제 버퍼 메모리 사용량 변화 확인info replication: 레플리카 동기화 상태, 오프셋 지연 확인LATENCY HISTORY: 명령 지연시간이 비정상적으로 증가하지 않는지 확인
# 업그레이드 후 빠른 상태 확인
redis-cli INFO server | grep redis_version
redis-cli INFO server | grep io_threads_active
redis-cli INFO stats | grep instantaneous_ops_per_sec
redis-cli INFO memory | grep used_memory_human
정리
Redis 8.0의 변경점을 한눈에 정리하면 이렇습니다.
| 변경점 | 이전 | Redis 8.0 |
|---|---|---|
| I/O 스레딩 | 옵트인, 쓰기만 | 기본 활성, 읽기+쓰기, 자동 감지 |
| 벡터 검색 | RediSearch 모듈 별도 설치 | 코어 내장 |
| 복제 버퍼 | 레플리카별 독립 버퍼 | 공유 복제 버퍼 (~80% 절감) |
| 내부 인코딩 | ziplist 일부 잔존 | listpack 전환 완료 |
| Hash 필드 TTL | 미지원 | HEXPIRE, HTTL 등 지원 |
| 클러스터 검색 | Cross-slot 제약 | FT.SEARCH 클러스터 분산 지원 |
| 라이선스 | BSD | RSALv2 + SSPLv1 |
공부하면서 느낀 건, Redis 8.0은 단순한 마이너 개선이 아니라 "Redis가 무엇인가"에 대한 정의 자체를 바꾸는 릴리스라는 점입니다. 캐시 + 데이터 구조 서버에서 ** 벡터 검색, JSON, 시계열까지 아우르는 통합 데이터 플랫폼 **으로의 전환을 선언한 것이니까요. 다만 라이선스 변경이라는 큰 변수가 있으므로, 조직의 상황에 맞게 Redis 8.0과 Valkey 중 어떤 선택이 적합한지 함께 검토하는 것이 좋겠습니다.