Redis 주니어 코딩 면접
새 면접Q. 온라인 투표 시스템에서 각 항목에 대한 투표 수를 집계하고, 중복 투표를 방지해야 합니다. 사용자 ID와 투표 항목을 관리하기 위해 어떤 Redis 데이터 타입을 조합하여 사용하면 좋을지, 그리고 투표 등록과 중복 확인을 어떻게 구현할 수 있는지 설명해주세요.
투표 수 집계는 String 타입의 INCR 명령어를 사용하고(vote:item:A), 중복 투표 방지는 Set 타입을 활용합니다(voted:item:A에 사용자 ID 저장). 투표 시 SADD 명령어로 사용자 ID를 추가하고 반환값이 1이면(새로 추가됨) INCR로 투표 수를 증가시킵니다. 반환값이 0이면 이미 투표한 사용자이므로 중복 투표를 거부합니다. 전체 투표자 목록은 SMEMBERS로 조회할 수 있고, 특정 사용자의 투표 여부는 SISMEMBER로 확인할 수 있습니다.
- • String 타입과 INCR로 투표 수 집계
- • Set 타입으로 투표한 사용자 ID 저장하여 중복 방지
- • SADD 반환값으로 중복 여부 판단
- • SISMEMBER로 투표 여부 빠르게 확인
만약 사용자가 투표를 취소할 수 있는 기능을 추가한다면 어떤 명령어를 사용하고, 어떤 순서로 처리해야 할까요?
Q. Redis에서 여러 명령어를 원자적으로 실행하기 위해 Lua 스크립트를 사용할 수 있습니다. Lua 스크립트의 장점과 MULTI/EXEC 트랜잭션과의 차이점을 설명하고, EVAL 명령어를 사용할 때 주의해야 할 점을 말씀해주세요.
Lua 스크립트는 여러 명령어를 원자적으로 실행하면서 조건문과 반복문 등 프로그래밍 로직을 포함할 수 있습니다. MULTI/EXEC는 명령어를 큐에 담았다가 일괄 실행만 하지만, Lua는 실행 중 값을 읽고 조건에 따라 다른 명령을 실행할 수 있습니다. Lua 스크립트는 실행 중 다른 명령이 끼어들 수 없어 원자성이 보장됩니다. 주의할 점은 스크립트가 길면 Redis를 블로킹하므로 빠르게 실행되도록 작성해야 하고, 스크립트 내에서 시간에 의존하는 로직이나 랜덤 값을 사용할 때는 복제 환경에서 일관성 문제가 생길 수 있습니다.
- • 조건문, 반복문 등 프로그래밍 로직 사용 가능
- • 실행 중 값을 읽고 판단하여 다음 명령 결정 가능
- • 원자적 실행으로 동시성 문제 해결
- • 긴 스크립트는 Redis 블로킹 유발 주의
EVALSHA 명령어는 무엇이며, EVAL 대신 EVALSHA를 사용하면 어떤 이점이 있나요?
Q. Redis의 Bitmap(비트맵)은 String 타입을 비트 단위로 조작하는 기능입니다. 일일 사용자 활동 로그를 기록할 때 Bitmap을 사용하면 메모리를 절약할 수 있는 이유와, SETBIT, GETBIT, BITCOUNT 명령어를 활용한 구현 방법을 설명해주세요.
Bitmap은 각 사용자를 비트 하나로 표현하여 메모리를 크게 절약할 수 있습니다. 예를 들어 1억 명 사용자의 일일 활동을 저장할 때 각 사용자당 1비트만 사용하므로 약 12MB만 필요합니다. SETBIT 명령어로 특정 사용자 ID 위치의 비트를 1로 설정하여 활동을 기록하고(SETBIT active:2024-01-01 userId 1), GETBIT로 특정 사용자의 활동 여부를 확인하며, BITCOUNT로 해당 날짜의 전체 활성 사용자 수를 집계할 수 있습니다. BITOP 명령어로 여러 날짜의 비트맵을 AND, OR 연산하여 연속 활동 사용자나 기간별 활동 패턴을 분석할 수도 있습니다.
- • 사용자당 1비트로 메모리 효율적
- • SETBIT로 활동 기록, GETBIT로 확인
- • BITCOUNT로 활성 사용자 수 집계
- • BITOP으로 여러 기간 데이터 비교 분석
사용자 ID가 연속적이지 않고 UUID처럼 불규칙한 경우 Bitmap을 사용할 때 어떤 문제가 발생할 수 있나요?
Q. Redis의 Geospatial 기능을 사용하면 위치 기반 서비스를 구현할 수 있습니다. GEOADD, GEORADIUS 명령어의 사용법과, 주변 매장 찾기 기능을 구현할 때 어떻게 활용할 수 있는지 설명해주세요.
GEOADD 명령어로 매장의 경도, 위도, 매장ID를 저장합니다(GEOADD stores 127.0 37.5 store1). GEORADIUS 명령어로 특정 좌표를 중심으로 반경 내의 매장을 검색할 수 있으며, 거리 단위(m, km)와 결과 개수를 지정할 수 있습니다. WITHDIST 옵션으로 거리 정보를, WITHCOORD로 좌표를, ASC/DESC로 정렬 순서를 지정할 수 있습니다. GEORADIUSBYMEMBER는 저장된 매장을 기준으로 주변 매장을 찾을 때 유용합니다. 내부적으로 Sorted Set을 사용하며 Geohash 알고리즘으로 위치를 점수로 변환하여 저장합니다.
- • GEOADD로 경도, 위도, 식별자 저장
- • GEORADIUS로 반경 내 위치 검색
- • WITHDIST, WITHCOORD 옵션으로 상세 정보 조회
- • 내부적으로 Sorted Set과 Geohash 사용
GEORADIUS 대신 GEOSEARCH 명령어를 사용하는 것이 권장되는 이유는 무엇인가요?
Q. Redis Stream은 로그나 이벤트 데이터를 저장하고 처리하는 데이터 구조입니다. Stream의 특징과 XADD, XREAD, XGROUP 명령어를 사용한 메시지 큐 구현 방법을 설명하고, Pub/Sub과 비교했을 때 어떤 차이점이 있는지 말씀해주세요.
Stream은 시간 순서대로 메시지를 저장하며 각 메시지는 고유 ID를 가집니다. XADD로 메시지를 추가하고, XREAD로 특정 ID 이후의 메시지를 읽을 수 있습니다. Consumer Group(XGROUP CREATE)을 생성하면 여러 컨슈머가 메시지를 분산 처리할 수 있고, 각 컨슈머는 서로 다른 메시지를 받습니다. XACK로 메시지 처리 완료를 확인하며, 미확인 메시지는 XPENDING으로 조회 가능합니다. Pub/Sub과 달리 메시지가 영구 저장되고, 컨슈머가 오프라인이어도 나중에 읽을 수 있으며, 메시지 처리 실패 시 재시도가 가능합니다. Kafka와 유사한 기능을 제공하지만 더 간단합니다.
- • 메시지 영구 저장 및 고유 ID 부여
- • Consumer Group으로 분산 처리 가능
- • XACK로 메시지 처리 확인 및 재시도 지원
- • Pub/Sub과 달리 메시지 영속성 보장
Stream의 메시지가 무한정 증가하는 것을 방지하기 위해 MAXLEN 옵션을 사용할 때, 대략적인 길이 제한(~)을 사용하는 이유는 무엇인가요?
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!