Redis SCAN 명령의 내부 동작 원리와 Rehashing 시나리오 분석
핵심 내용
SCAN은 Cursor의 비트 역순 증분과 이중 해시 테이블 탐색으로 Rehashing 중에도 일관된 순회를 보장한다.
자세히 보기
Redis의 SCAN 명령은 KEYS 명령처럼 서버를 블로킹하지 않으면서 키를 순회할 수 있는 대안입니다. 이 글은 SCAN의 사용법을 넘어, 소스 코드를 통해 Rehashing 상황에서도 데이터 누락 없이 동작하는 내부 원리를 분석합니다.
SCAN의 기본 구조와 Cursor
SCAN, SSCAN, ZSCAN, HSCAN은 공통 함수 scanGenericCommand를 통해 처리됩니다. Cursor 값을 0으로 시작해 반환된 Cursor가 0이 될 때까지 반복하는 전체 순회(full iteration) 방식을 따릅니다. Cursor는 단순히 다음 인덱스를 의미하지 않으며, 실제 구현에서는 비트 역순(reverse) 증분 방식을 사용합니다. 이는 순회의 시작과 끝을 모두 0으로 맞춰 종료 조건을 명확히 하기 위함입니다.
Rehashing 중의 이중 테이블 탐색
Redis는 해시 테이블이 특정 비율을 초과하면 크기를 2배로 늘리고 Rehashing을 진행합니다. 이때 한 번에 모든 데이터를 이동하지 않고, rehashidx를 이용해 한 스텝마다 하나의 Bucket만 이동하는 점진적 Rehashing을 수행합니다. 이 과정에서 ht[0](구 테이블)과 ht[1](신 테이블)이 동시에 존재합니다.
SCAN은 Rehashing 중일 때 두 테이블을 모두 고려합니다. 먼저 작은 테이블(ht[0])의 Bucket을 순회한 후, 해당 인덱스에 대응하는 큰 테이블(ht[1])의 Bucket들을 추가로 탐색합니다. 이를 통해 아직 이동되지 않은 데이터와 이미 이동된 데이터를 모두 포함하여 반환하므로, Rehashing 중에도 일관된 결과를 제공합니다.
SCAN의 한계와 주의사항
SCAN은 KEYS의 단점을 보완했지만 다음과 같은 제약이 있습니다.
- 정확한 개수 보장 불가:
COUNT옵션은 힌트일 뿐, 정확히 그 개수를 반환하지 않습니다. - 중복 및 누락 가능성: Rehashing이나 테이블 확장이 일어나는 동안 Cursor가 이미 지나간 위치의 데이터는 반환되지 않거나, 특정 항목이 중복 반환될 수 있습니다.
- 자료구조 의존성: Set이나 Hash가 ziplist로 인코딩된 경우, SCAN은 내부적으로 전체 데이터를 한 번에 가져오므로 KEYS와 유사한 성능 저하가 발생할 수 있습니다.
이 한국어 요약은 AI가 자동으로 만들었습니다. 원문의 주장과 맥락은 원문에서 확인해 주세요. 저작권은 원저작자에게 있습니다.