Redis 미드레벨 기술면접
새 면접Q. Redis의 Geospatial 자료구조를 사용하여 위치 기반 서비스를 구현하려고 합니다. GEOADD, GEORADIUS, GEODIST 명령어의 동작 원리를 설명하고, 내부적으로 Sorted Set과 Geohash를 어떻게 활용하는지 설명해주세요. 또한 대규모 위치 데이터를 다룰 때의 성능 특성과 한계점을 제시해주세요.
Redis Geo는 내부적으로 Sorted Set을 사용하며, 위도/경도를 52비트 Geohash로 인코딩하여 score로 저장합니다. GEOADD는 좌표를 Geohash로 변환 후 ZADD로 저장하고, GEORADIUS는 중심점 기준으로 9개 영역의 Geohash 범위를 계산하여 ZRANGEBYSCORE로 후보를 추출한 뒤 정확한 거리를 재계산합니다. Geohash는 근접한 위치를 비슷한 해시값으로 매핑하지만 경계 지점에서 불연속성이 있어 주변 셀도 검색해야 합니다. 대규모 데이터에서는 전체 데이터를 하나의 키에 저장하면 메모리와 검색 성능 문제가 발생하므로, 지역별로 키를 분할하거나 S2 Geometry 같은 외부 라이브러리 사용을 고려해야 합니다.
- • Geohash를 사용해 2차원 좌표를 1차원 정수로 변환하여 Sorted Set에 저장
- • GEORADIUS는 중심점 기준 9개 Geohash 영역을 검색 후 정확한 거리 계산
- • Geohash 경계 불연속성으로 인해 인접 셀 검색 필요
- • 대규모 데이터는 지역별 키 분할 또는 외부 공간 인덱스 라이브러리 활용
Geohash의 정밀도(precision)에 따른 오차 범위는 어떻게 결정되며, Redis에서 사용하는 52비트 Geohash가 제공하는 정밀도는 얼마나 되나요?
Q. Redis 4.0부터 도입된 Module System의 개념과 활용 사례를 설명해주세요. RedisJSON, RedisGraph, RedisTimeSeries 같은 주요 모듈들의 특징을 설명하고, 자체 모듈을 개발할 때 고려해야 할 사항과 네이티브 명령어 대비 성능 특성을 설명해주세요.
Redis Module System은 C API를 통해 Redis 코어를 확장할 수 있는 동적 라이브러리 로딩 메커니즘입니다. RedisJSON은 JSON 문서를 네이티브 자료구조로 저장하고 경로 기반 쿼리를 제공하며, RedisGraph는 그래프 데이터베이스 기능을, RedisTimeSeries는 시계열 데이터 압축과 집계를 지원합니다. 모듈 개발 시 Redis의 단일 스레드 모델을 고려해야 하며, 긴 실행 시간을 가진 작업은 백그라운드 스레드로 분리하고, 메모리 관리는 Redis의 allocator를 사용해야 합니다. 네이티브 명령어보다 함수 호출 오버헤드가 있지만, 복잡한 연산을 서버 측에서 처리하여 네트워크 왕복을 줄이면 전체 성능이 향상될 수 있습니다.
- • C API 기반 동적 라이브러리로 Redis 기능 확장 가능
- • RedisJSON, RedisGraph, RedisTimeSeries 등 특화된 자료구조 제공
- • 단일 스레드 모델 고려 필수, 긴 작업은 백그라운드 스레드 활용
- • 네트워크 왕복 감소로 복잡한 연산의 전체 성능 향상 가능
Redis Module에서 새로운 자료구조를 정의할 때 RDB 저장과 AOF 재작성을 지원하기 위해 구현해야 하는 콜백 함수들은 무엇인가요?
Q. Redis Pipelining의 동작 원리를 TCP 프로토콜 관점에서 설명하고, RTT(Round Trip Time) 감소 효과를 구체적으로 분석해주세요. Pipelining과 Transaction, Lua Script의 차이점을 원자성과 성능 측면에서 비교하고, 각각을 선택해야 하는 상황을 제시해주세요.
Pipelining은 여러 명령어를 한 번에 전송하고 응답을 일괄 수신하여 네트워크 RTT를 줄이는 기법입니다. 일반적으로 명령어당 1 RTT가 필요하지만, N개 명령어를 파이프라이닝하면 총 1 RTT로 줄어들어 네트워크 지연이 큰 환경에서 수십 배 성능 향상이 가능합니다. Transaction은 MULTI/EXEC로 원자성을 보장하지만 명령어가 큐잉되어 중간 결과를 사용할 수 없고, Pipelining은 원자성을 보장하지 않지만 명령어가 즉시 실행되며 RTT만 감소시킵니다. Lua Script는 원자성과 중간 결과 활용이 모두 가능하지만 스크립트 작성과 관리가 필요합니다. 단순 대량 쓰기는 Pipelining, 원자성이 필요하면 Transaction, 조건부 로직이 필요하면 Lua Script를 선택합니다.
- • 여러 명령어를 한 번에 전송하여 RTT를 N회에서 1회로 감소
- • Pipelining은 원자성 미보장, Transaction은 원자성 보장하나 중간 결과 사용 불가
- • Lua Script는 원자성과 조건부 로직 모두 지원하지만 복잡도 증가
- • 네트워크 지연이 클수록 Pipelining 효과가 크게 나타남
Pipelining 사용 시 한 번에 보낼 수 있는 명령어 개수의 제한이 있나요? 너무 많은 명령어를 파이프라이닝하면 어떤 문제가 발생할 수 있나요?
Q. Redis의 BLPOP, BRPOP, BRPOPLPUSH 같은 블로킹 명령어의 내부 동작 원리를 설명해주세요. 단일 스레드 모델에서 어떻게 블로킹을 구현하는지, 여러 클라이언트가 동시에 같은 키를 대기할 때 공정성(fairness)은 어떻게 보장되는지, 그리고 타임아웃 처리 메커니즘을 설명해주세요.
Redis는 단일 스레드지만 블로킹 명령어 실행 시 클라이언트를 blocked_clients 리스트에 등록하고 이벤트 루프로 돌아가 다른 명령어를 처리합니다. 데이터가 리스트에 추가되면 대기 중인 클라이언트를 깨워 응답을 전송합니다. 여러 클라이언트가 동시에 대기할 때는 FIFO 순서로 처리되어 먼저 블로킹한 클라이언트가 먼저 데이터를 받습니다. 타임아웃은 시간 기반 이벤트로 관리되며, 만료 시 클라이언트에게 NULL 응답을 보내고 blocked_clients에서 제거합니다. BRPOPLPUSH는 원자적으로 한 리스트에서 팝하여 다른 리스트에 푸시하므로 reliable queue 패턴 구현에 사용됩니다.
- • blocked_clients 리스트에 클라이언트 등록 후 이벤트 루프로 복귀
- • 데이터 도착 시 대기 클라이언트를 FIFO 순서로 깨워 공정성 보장
- • 타임아웃은 시간 기반 이벤트로 관리되며 만료 시 NULL 응답
- • BRPOPLPUSH는 원자적 팝-푸시로 reliable queue 패턴 지원
Redis Cluster 환경에서 블로킹 명령어 사용 시 키가 다른 노드로 마이그레이션되면 어떤 일이 발생하나요?
Q. Redis 6.0에서 도입된 Client-Side Caching의 동작 원리와 Tracking 모드(Broadcasting vs OPTIN/OPTOUT)의 차이를 설명해주세요. Invalidation Message를 받는 메커니즘과 RESP3 프로토콜의 역할, 그리고 실무에서 클라이언트 측 캐시를 구현할 때 고려해야 할 메모리 관리와 일관성 문제를 설명해주세요.
Client-Side Caching은 클라이언트가 읽은 데이터를 로컬 메모리에 캐시하고, 서버가 데이터 변경 시 invalidation message를 전송하여 캐시를 무효화하는 메커니즘입니다. Broadcasting 모드는 특정 키 prefix를 구독하여 해당 패턴의 모든 변경을 수신하고, OPTIN/OPTOUT 모드는 명시적으로 추적할 키만 등록하여 네트워크 트래픽을 줄입니다. RESP3 프로토콜은 Push 타입을 지원하여 클라이언트 요청 없이 서버가 invalidation을 전송할 수 있습니다. 클라이언트는 LRU나 LFU로 캐시 크기를 제한해야 하며, 네트워크 지연으로 invalidation이 늦게 도착하면 stale read가 발생할 수 있으므로 TTL 기반 추가 만료 정책이 필요합니다.
- • 서버가 데이터 변경 시 invalidation message를 클라이언트에 푸시
- • Broadcasting은 prefix 기반, OPTIN/OPTOUT은 명시적 키 추적으로 트래픽 절감
- • RESP3 프로토콜의 Push 타입으로 비동기 invalidation 전송
- • 클라이언트는 LRU/LFU로 메모리 관리, TTL로 stale read 방지 필요
Client-Side Caching을 사용할 때 Redis Cluster 환경에서 노드 간 데이터 이동이나 failover 발생 시 캐시 일관성을 어떻게 보장할 수 있나요?
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!