Redis 캐시 업데이트 시 발생하는 경쟁 조건(Race Condition) 문제를 방지하기 위해 어떤 방법들을 사용할 수 있으며, 특히 복잡한 로직을 원자적으로 실행해야 할 경우 Redis의 Lua 스크립트를 어떻게 활용할 수 있는지 구체적인 예시와 함께 설명해 주세요.
힌트 · SET NX PX, 분산 락(Redlock), WATCH/MULTI/EXEC 트랜잭션, 그리고 Lua 스크립트의 원자성을 활용한 복합 연산 구현을 설명하세요.
모범답안
Redis 캐시 업데이트 시 경쟁 조건은 여러 클라이언트가 동시에 같은 키를 수정하려 할 때 발생할 수 있습니다. 이를 방지하기 위해 몇 가지 방법을 사용할 수 있습니다.
가장 간단한 방법은 SET NX PX 명령을 사용하는 것입니다. NX 옵션은 키가 존재하지 않을 때만 값을 설정하고, PX는 만료 시간을 밀리초 단위로 설정합니다. 이를 통해 락을 획득하고, 작업이 끝나면 자동으로 해제되도록 할 수 있습니다.
분산 락을 구현하는 더 강력한 방법으로는 Redlock 알고리즘이 있습니다. Redlock은 여러 Redis 인스턴스를 사용하여 락의 안정성을 높입니다.
복잡한 로직을 원자적으로 실행해야 할 경우에는 Lua 스크립트를 활용할 수 있습니다. Redis는 Lua 스크립트를 원자적으로 실행하므로, 스크립트 내에서 여러 명령을 순차적으로 실행하여 경쟁 조건을 방지할 수 있습니다. 예를 들어, 특정 키의 값을 증가시키고, 그 값이 특정 임계값을 넘는지 확인하는 로직을 하나의 Lua 스크립트로 구현할 수 있습니다.
-- Lua 스크립트 예시
local current = redis.call("INCR", KEYS[1])
if current > tonumber(ARGV[1]) then
return 1
else
return 0
end
이 스크립트는 INCR 명령과 조건문을 원자적으로 실행하여, 여러 클라이언트가 동시에 값을 증가시키더라도 임계값을 정확하게 관리할 수 있도록 합니다.
읽었다면, 이제 직접 답해볼 차례예요
패스잇 앱에서 이 질문에 말로 답하면 AI가 꼬리질문까지 이어가며 1:1 코칭합니다.
함께 보는 캐시 (Redis) 면접 질문
- 분산 환경에서 Redis 캐시를 사용할 때, 데이터 일관성을 유지하기 위한 전략과 발생할 수 있는 문제점(예: stale data)을 설명하고, 이를 해결하기 위한 구체적인 방안들을 제시해 주세요.
- 대규모 트래픽을 처리하는 서비스에서 Redis Cluster를 구축한다고 가정할 때, 데이터 샤딩 전략(예: 해시 태그) 선택 기준과 특정 키가 특정 슬롯에 할당되도록 제어하는 방법, 그리고 클러스터 재편성(resharding) 시 발생할 수 있는 성능 저하를 최소화하는 방안에 대해 설명해 주세요.
- Redis의 maxmemory-policy 설정이 서비스의 데이터 접근 패턴 및 메모리 사용량에 미치는 영향을 심층적으로 분석하고, 특정 워크로드(예: 실시간 랭킹, 세션 관리)에 최적화된 정책을 선택하기 위한 기준과 추가적인 성능 튜닝 방안(예: maxmemory-samples, 데이터 구조 선택)을 설명해 주세요.
- 서비스 시작 직후 또는 특정 캐시 키 만료 시점에 다수의 요청이 동시에 캐시 미스(cache miss)를 발생시켜 백엔드 시스템에 과부하를 주는 Cache Stampede(또는 Thundering Herd) 문제를 해결하기 위한 고급 전략들을 설명해 주세요.
- Redis의 RDB와 AOF 지속성(persistence) 메커니즘의 장단점을 비교하고, 데이터 손실을 최소화하면서 고가용성(High Availability) 및 재해 복구(Disaster Recovery)를 보장하기 위한 아키텍처 설계 방안(예: Redis Sentinel, Redis Cluster와 연동)을 설명해 주세요.
- Redis에서 특정 키(Hot Key)에 대한 접근이 집중되거나, 매우 큰 키(Big Key)가 존재할 때 발생할 수 있는 성능 문제(예: 네트워크 대역폭 소모, CPU 부하)를 설명하고, 이를 진단하고 완화하기 위한 구체적인 방법들을 제시해 주세요.