Redis 다중 키 연산

Redis 다중 키 연산 (Multi-key operations)

Redis의 다중 키 연산은 단일 명령으로 여러 키를 다룰 수 있게 해주지만, 그 동작은 Redis 설정과 클러스터링 구성에 따라 크게 달라져요. 이 페이지는 다양한 Redis 구성에서 다중 키 연산을 다루는 개발자를 위한 빠른 참조자료예요.

출처: 공식문서

구성(Configurations)

Redis는 서로 다른 다중 키 명령 동작을 보이는 다섯 가지 구성을 지원합니다:

  1. ROS/RS 클러스터링 비활성 - 단일 Redis 인스턴스
  2. ROS, 클러스터링 활성 - Redis 오픈소스 클러스터
  3. RS, 클러스터링 활성, OSS 클러스터 API 활성 - ROS 클러스터 호환성을 가진 Redis Software
  4. RS, 클러스터링 활성, OSS 클러스터 API 비활성 - Redis Software 독점 클러스터링
  5. RS, Active-Active - Redis Software Active-Active (단일 샤드여도 클러스터로 간주)

ROS는 Redis Open Source, RS는 Redis Software를 뜻합니다.

명령 동작

각 구성에서 명령은 세 가지 동작 중 하나를 보여줘요:

  • single-slot: 명령은 같은 해시 슬롯 안의 키에만 동작해야 합니다
  • cross-slot (all shards): 명령은 클러스터의 모든 샤드에 걸쳐 동작할 수 있어요
  • cross-slot (within a single shard): 명령은 슬롯을 걸쳐 동작할 수 있지만 단일 샤드 안에서만 동작해요

읽기 전용 명령

동작 명령
ROS/RS 클러스터링 비활성:
– 전체 DB (단일 샤드)

ROS 클러스터링 활성, RS 클러스터링 활성 (OSS 클러스터 API 활성):
– 현재 샤드

RS 클러스터링 활성 (OSS 클러스터 API 비활성):
– 모든 샤드
DBSIZE, KEYS, SCAN
ROS/RS 클러스터링 비활성:
– cross-slot

ROS 클러스터링 활성, RS 클러스터링 활성 (OSS 클러스터 API 활성):
– single-slot

RS 클러스터링 활성 (OSS 클러스터 API 비활성):
– cross-slot (all shards)
EXISTS, MGET
ROS/RS 클러스터링 비활성:
– cross-slot

ROS 클러스터링 활성, RS 클러스터링 활성 (OSS 클러스터 API 활성), RS 클러스터링 활성 (OSS 클러스터 API 비활성):
– single-slot
PFCOUNT, SDIFF, SINTER, SINTERCARD, SUNION, WATCH, XREAD, XREADGROUP, ZDIFF, ZINTER, ZINTERCARD, ZUNION
ROS/RS 클러스터링 비활성:
– cross-slot

ROS 클러스터링 활성, RS 클러스터링 활성 (OSS 클러스터 API 활성), RS 클러스터링 활성 (OSS 클러스터 API 비활성):
– single-shard
JSON.MGET

사용자는 CROSSSLOT 오류를 받지 않아요. 하지만 클러스터링이 켜졌고 지정된 모든 키가 같은 슬롯에 없으면, 현재 샤드의 모든 슬롯에 대해 부분 결과를 받습니다.
ROS/RS 클러스터링 비활성:
– cross-slot (all shards)

ROS 클러스터링 활성, RS 클러스터링 활성 (OSS 클러스터 API 활성), RS 클러스터링 활성 (OSS 클러스터 API 비활성):
– cross-slot (all shards), 트랜잭션의 일부가 될 수 없음
TS.MGET, TS.MRANGE, TS.MREVRANGE, TS.QUERYINDEX

읽기-쓰기 명령

동작 명령
ROS/RS 클러스터링 비활성:
– 전체 DB (단일 샤드)

ROS 클러스터링 활성, RS 클러스터링 활성 (OSS 클러스터 API 활성):
– 현재 샤드

RS 클러스터링 활성 (OSS 클러스터 API 비활성):
– 모든 샤드
FLUSHALL, FLUSHDB
ROS/RS 클러스터링 비활성:
– cross-slot

ROS 클러스터링 활성, RS 클러스터링 활성 (OSS 클러스터 API 활성):
– single-slot

RS 클러스터링 활성 (OSS 클러스터 API 비활성):
– cross-slot (all shards)
DEL, MSET, TOUCH, UNLINK

참고: Active-Active에서는 DEL, MSET, UNLINK가 single-slot
ROS/RS 클러스터링 비활성:
– cross-slot

ROS 클러스터링 활성, RS 클러스터링 활성 (OSS 클러스터 API 활성), RS 클러스터링 활성 (OSS 클러스터 API 비활성):
– single-slot
BITOP, BLMOVE, BLMPOP, BLPOP, BRPOP, BRPOPLPUSH, BZMPOP, BZPOPMAX, BZPOPMIN, CMS.MERGE, COPY, GEORADIUS or GEORADIUSBYMEMBER (with STORE or STOREDIST), GEOSEARCHSTORE, JSON.MSET, LMOVE, LMPOP, MSETNX, PFMERGE, RENAME, RENAMENX, RPOPLPUSH, SDIFFSTORE, SINTERSTORE, SMOVE, SUNIONSTORE, TDIGEST.MERGE, TS.MADD, ZDIFFSTORE, ZINTERSTORE, ZMPOP, ZRANGESTORE, ZUNIONSTORE
ROS/RS 클러스터링 비활성:
– cross-slot

ROS 클러스터링 활성, RS 클러스터링 활성 (OSS 클러스터 API 활성), RS 클러스터링 활성 (OSS 클러스터 API 비활성):
– single-shard
TS.CREATERULE, TS.DELETERULE

사용자는 CROSSSLOT 오류를 받지 않아요. 하지만 클러스터링이 켜졌고 두 지정 키가 같은 슬롯에 없으면 (error) ERR TSDB: the key does not exist를 받습니다.

파이프라인, 트랜잭션, 스크립트

동작 연산
ROS/RS 클러스터링 비활성:
– cross-slot
ROS 클러스터링 활성, RS 클러스터링 활성 (OSS 클러스터 API 활성):
– single-slot
RS 클러스터링 활성 (OSS 클러스터 API 비활성):
– cross-slot (all shards)
파이프라인
ROS/RS 클러스터링 비활성:
– cross-slot
ROS 클러스터링 활성, RS 클러스터링 활성 (OSS 클러스터 API 활성), RS 클러스터링 활성 (OSS 클러스터 API 비활성):
– single-slot
MULTI/EXEC 트랜잭션 안의 키
EVAL 또는 EVALSHA로 실행하는 Lua 스크립트 안의 키

구성별 예시

단일 인스턴스 (클러스터링 없음)

단일 Redis 인스턴스에서는 모든 다중 키 연산이 제약 없이 동작해요:

# 파이프라인 연산은 어떤 키에도 동작합니다
PIPELINE
SET user:1 "Alice"
SET product:100 "Widget"
GET user:1
GET product:100
EXEC

# 트랜잭션은 어떤 키에도 동작합니다
MULTI
SET counter:a 1
SET counter:b 2
INCR counter:a
INCR counter:b
EXEC

클러스터 환경

클러스터 환경에서는 슬롯 분포를 고려해야 해요:

# 키가 다른 슬롯에 있으면 실패할 수 있습니다
MSET user:1 "Alice" user:2 "Bob"

# 해시 태그를 써서 같은 슬롯을 보장하세요
MSET {users}:1 "Alice" {users}:2 "Bob"

# 키가 어떤 슬롯에 속하는지 확인하세요
CLUSTER KEYSLOT user:1
CLUSTER KEYSLOT {users}:1

Active-Active 데이터베이스

Active-Active 데이터베이스에는 쓰기 연산에 대한 추가 제약이 있어요:

# 읽기 연산은 슬롯을 걸쳐 동작할 수 있습니다
MGET user:1 user:2 product:100

# 쓰기 연산은 같은 슬롯에 있어야 합니다
MSET {data}:user:1 "Alice" {data}:user:2 "Bob"

다중 키 연산 문제 해결

일반적인 오류 메시지

  • CROSSSLOT: 요청의 키들이 같은 슬롯으로 해시되지 않음
  • MOVED: 키가 다른 노드로 이동됨 (resharding 중)
  • TRYAGAIN: 연산이 일시적으로 사용 불가 (마이그레이션 중)

해결 방법

  1. 해시 태그(hash tags) 사용 - 연관된 키를 그룹화
  2. 데이터 모델 재설계 - cross-slot 연산 최소화
  3. 오류 중 클러스터 상태 확인
  4. 일시적 실패에 대한 재시도 로직 구현

성능 고려 사항

  • Single-slot 연산은 조정(coordinator)이 필요 없어 가장 빠릅니다
  • Cross-slot 연산은 내부 라우팅 때문에 지연이 더 높을 수 있어요
  • 패턴 명령(KEYS, FLUSHALL)은 모든 샤드를 스캔해서 비쌀 수 있습니다
  • 모듈 연산은 최적화된 cross-slot 구현을 가질 수 있어요

자신의 다중 키 연산 요구사항에 맞춰 Redis 구성을 선택하고 데이터 모델을 설계하세요.

더 알아보기 (Learn more)