한 줄 요약: Valkey 9.0부터 새 설정 cluster-databases (기본값 1, immutable) 를 2 이상으로 잡으면 클러스터 모드에서도 SELECT n 으로 여러 논리 DB를 쓸 수 있음. 다만 SWAPDB 는 여전히 차단되고 슬롯 해싱은 DB와 무관하게 공통이라 핫키 회피 수단은 아님.

개요

Valkey 9.0 이전까지 클러스터 모드는 DB 0 한 개만 허용했음. SELECT 1 같은 명령은 (error) ERR SELECT is not allowed in cluster mode 로 거부됐음 (valkey/valkey:8.1.6 으로 직접 재현).

9.0부터 새 설정 cluster-databases (기본값 1) 를 통해 클러스터에서 사용할 DB 개수를 명시적으로 열어야 함. databases 16 만 켜는 것으로는 동작하지 않고 cluster-databases 를 함께 지정해야 한다는 점이 핵심임. 공식 명세 Valkey Cluster SpecificationImplemented subset 절에 다음 한 줄이 9.0 시점에 추가됐음.

Starting with version 9.0, Valkey cluster supports multiple databases, similar to standalone mode but with some additional restrictions.

테스트 환경: valkey/valkey:9.0 (valkey_version:9.0.3), Docker 29.3.1.

결론

항목9.0 이전9.0+
클러스터에서 SELECT n거부cluster-databases ≥ 2 일 때만 허용
활성화 방법cluster-databases 를 2 이상으로 (기본값 1)
변경성immutableCONFIG SET 거부, 재시작 필요
격리 단위DB별 키 격리. 슬롯 해싱은 DB와 무관하게 공유
클러스터 차단 명령SELECT (DB 0 외), SWAPDBSWAPDB (SELECT 는 범위 내 허용)
업그레이드 동작기본값 1 이라 업그레이드만으로는 비활성

운영 시 기억할 점.

  • cluster-databasesimmutable 이라 한 번 정한 값을 바꾸려면 모든 노드를 재시작해야 함. 도입 시 향후 필요량을 넉넉히 잡고 시작할 것.
  • 슬롯 해싱은 DB와 무관하게 공통이므로 핫슬롯·핫키 문제는 DB를 쪼갠다고 완화되지 않음. 멀티 테넌시 분리가 목적이라면 테넌트별 key prefix 또는 별도 클러스터가 여전히 유효한 옵션임.
  • SWAPDB 가 차단돼 있어 standalone에서 쓰던 “빈 DB에 적재 후 교체” 패턴은 클러스터에서 재현 불가. 블루/그린 클러스터 전환 또는 key prefix 롤아웃이 대안.

변경 사항 — 두 개의 설정 변수

설정역할기본값변경성
databasesstandalone/클러스터 공통 상한16immutable
cluster-databases클러스터 모드에서의 실제 상한1immutable

두 값 중 작은 쪽 이 실질적인 제한임 — SELECT n 에서 nmin(databases, cluster-databases) 이상이면 ERR DB index is out of range. 두 설정 모두 immutable 이라 CONFIG SET 으로 변경할 수 없고, 값을 바꾸려면 프로세스를 재시작해야 함.

127.0.0.1:6379> CONFIG SET cluster-databases 8
(error) ERR CONFIG SET failed (possibly related to argument 'cluster-databases') - can't set immutable config

같은 클러스터의 모든 노드가 동일한 cluster-databases 값을 갖도록 맞춰야 함. 값이 다른 노드가 섞이면 SELECT 허용 범위가 노드별로 엇갈려 클라이언트 동작이 흔들림.

기존 클러스터에 적용

이미 동작하는 Valkey 클러스터에 멀티 DB를 켜려면 valkey-server 기동 옵션에 다음 두 줄만 추가하면 됨. cluster-enabled yes, cluster-node-timeout, cluster-config-file, 포트·바인드 같은 나머지 클러스터 구성은 그대로 두면 됨.

command: >
  valkey-server
  ...
  --databases 16
  --cluster-databases 4
  • databases : standalone과 공통인 DB 상한(기본 16).
  • cluster-databases : 클러스터에서 실제로 열리는 DB 개수(기본 1, 반드시 2 이상 지정).

모든 노드에 동일한 cluster-databases 값을 적용해야 함. 값이 불일치하는 노드가 섞이면 SELECT 허용 범위가 달라져 클라이언트 동작이 노드별로 엇갈림.

설정 확인

docker exec valkey-1 valkey-cli CONFIG GET cluster-databases
cluster-databases
4

DB 격리 테스트

같은 키를 DB 0, DB 1에 서로 다른 값으로 저장하고 격리 여부 확인함.

# DB 0 쓰기
docker exec valkey-1 valkey-cli -c -n 0 SET user:100 alice
docker exec valkey-1 valkey-cli -c -n 0 GET user:100
 
# DB 1 쓰기 (같은 키, 다른 값)
docker exec valkey-1 valkey-cli -c -n 1 SET user:100 bob
docker exec valkey-1 valkey-cli -c -n 1 GET user:100
 
# DB 0 값은 그대로 유지
docker exec valkey-1 valkey-cli -c -n 0 GET user:100
OK
alice
OK
bob
alice

슬롯 라우팅은 DB별로 독립 적용

각 DB에서도 기존 슬롯 해싱(CRC16 mod 16384)이 그대로 동작함. 즉 DB 1에 쓴 키도 슬롯을 소유한 노드로 자동 라우팅됨.

-c (cluster redirect) 옵션 없이 슬롯 비소유 노드에 직접 쓰면 MOVED 가 그대로 떨어짐.

docker exec valkey-1 valkey-cli -n 1 SET moveprobe hello

valkey-1(슬롯 0–5460)에 쓰기를 시도하지만 moveprobe는 슬롯 8123이므로 valkey-2로 MOVED 됨.

(error) MOVED 8123 172.25.0.3:6379

MOVED 응답에는 슬롯·주소만 포함되고 DB 번호는 포함되지 않음. 클라이언트가 재접속한 뒤 다시 SELECT 1 을 수행해야 동일 DB 컨텍스트가 유지됨. valkey-cli -c 의 cluster redirect 모드는 현재 세션의 DB 컨텍스트를 유지한 채로 재전송해줌.

범위 밖 DB 인덱스

docker exec valkey-1 valkey-cli -c SELECT 4
(error) ERR DB index is out of range

cluster-databases=4 이면 유효한 범위는 0..3 임.

INFO keyspace — 노드 로컬 통계

INFO keyspace 는 접속한 노드가 보유한 슬롯에 들어 있는 키만 카운트함. 클러스터 전체 키 분포를 보려면 노드별로 따로 조회 후 합산해야 함.

해시 태그 {ns} 로 모든 키를 같은 슬롯으로 강제해, 한 노드에서 DB별 격리·카운트를 동시에 확인.

docker exec valkey-1 valkey-cli -c CLUSTER KEYSLOT '{ns}k1'
docker exec valkey-1 valkey-cli -c -n 0 SET '{ns}k1' v1
docker exec valkey-1 valkey-cli -c -n 1 SET '{ns}k1' v1
docker exec valkey-1 valkey-cli -c -n 2 SET '{ns}k1' v1
9937
OK
OK
OK

슬롯 9937 의 소유 노드(valkey-2, 슬롯 5461–10922 담당) 에서 INFO keyspace 를 조회하면 세 DB가 각각 1키씩 잡혀 있음.

docker exec valkey-2 valkey-cli INFO keyspace
# Keyspace
db0:keys=1,expires=0,avg_ttl=0,keys_with_volatile_items=0
db1:keys=1,expires=0,avg_ttl=0,keys_with_volatile_items=0
db2:keys=1,expires=0,avg_ttl=0,keys_with_volatile_items=0

다른 노드에서 같은 명령을 실행하면 이 슬롯에 속하지 않는 키만 나오므로 위 출력에 든 세 키는 등장하지 않음.

제약사항 (테스트로 확인)

1. SWAPDB 금지

docker exec valkey-1 valkey-cli SWAPDB 0 1
(error) ERR SWAPDB is not allowed in cluster mode

DB 단위 atomic swap(원자 교체)은 클러스터 전역에서 일관성을 보장하기 어려워 막아둔 것으로 보임.

2. cluster-databasesimmutable

CONFIG SET이 거부되므로 모든 노드를 순차 재시작해야 늘리거나 줄일 수 있음. 운영 중 스키마 확장이 필요한 경우 처음부터 여유 있게 잡아두는 게 안전함.

3. DB 간 명령은 일부만 허용됨

  • MOVE key db : 동작함. 같은 슬롯에 매핑되어야 하며, 대상 DB에 같은 키가 있으면 0 반환(기존 동작과 동일).
  • COPY src dst DB n : 동작함.
  • FLUSHDB / FLUSHALL : 동작함.
  • SWAPDB : 불가.
docker exec valkey-1 valkey-cli -c -n 0 SET movetest value1
docker exec valkey-1 valkey-cli -c -n 0 MOVE movetest 1
OK
1

4. CLUSTER KEYSLOT / COUNTKEYSINSLOT 는 현재 DB 기준

CLUSTER COUNTKEYSINSLOT은 클라이언트가 접속해 있는 현재 DB의 키만 카운트함. 클러스터 전체 슬롯 점유량이 아니므로 DB마다 개별 조회가 필요함.

docker exec valkey-1 valkey-cli -n 0 CLUSTER COUNTKEYSINSLOT 3221
docker exec valkey-1 valkey-cli -n 1 CLUSTER COUNTKEYSINSLOT 3221
1
1

참고