Playball Logo

Command Palette

Search for a command to run...

목차 열기

Redis 구성

Redis는 두 개의 독립적인 인스턴스로 분리하여 운영합니다. 티켓 오픈 시 대기열 트래픽이 폭발해도 인증과 좌석 분산 락 성능에 영향을 주지 않도록 설계했습니다.


인스턴스 분리 구성

공용 Redis :6379 (Gateway / Auth-Guard / Seat / Order-Core)

KeyType설명TTL
refresh_token:{jti}STRINGRefresh Token 저장 (IP/UA 포함)설정 가능 (기본 4시간)
token_blacklist:{jti}STRING로그아웃 토큰 차단남은 Access Token TTL
user-by-id:{userId}STRING (JSON)User DTO 분산 캐시10분
auth-me:{userId}STRING (JSON)/auth/me 응답 캐시30초
seat:booking-options:{m}:{u}STRING (JSON)예매 옵션 (추천/인원수/인접석)900초 (15분)
seat:recommendation:match:{m}:block:{b}Redisson RLock블럭 단위 분산 락 (Watch Dog)자동 갱신
seat:hold:match:{m}:seat:{s}Redisson RLock좌석 단위 분산 락5초 lease
seat-groups-response:{m}STRING (JSON)좌석맵 API 응답 캐시5초
matches-list-response:{date}STRING (JSON)경기 목록 API 응답 캐시30초
rate_limit:{ip}:{ep}STRING (INCR)Rate Limiting 카운터 (prod)60초

Queue 전용 Redis :6380

KeyType설명TTL
queue:wait:{matchId}ZSET대기열 사용자 순서 (score = 진입 타임스탬프)없음
queue:ready:{m}:{u}STRINGReady 상태 토큰 payload60초 (설정 가능)
queue:ready:index:{m}SETReady 유저 인덱스 (cleanup용)없음
queue:expired:{m}:{u}STRING만료 마커300초
queue:matchSET활성 티켓팅 경기 목록없음
queue:precheck:booking-option:{m}:{u}STRINGPreQueue 검증용 예매 옵션 마커900초

인스턴스 분리 이유

문제해결
대기열 폭발 시 Redis 부하 → 인증/락 지연Queue 전용 인스턴스 분리로 영향 차단
블랙리스트 확인 지연 → JWT 검증 병목공용 Redis(Auth/Lock)가 항상 안정적 응답 보장
좌석 분산 락 실패 → 동시성 이슈대기열 트래픽과 분리되어 락 성공률 보장

Redis 활용 전략 정리

1. 캐시 계층 (Caffeine vs Redis)

항목Caffeine (로컬)Redis (원격)
저장 위치JVM 힙 메모리별도 서버
접근 시간< 1μs0.5~2ms (+네트워크)
인스턴스 간 공유각자 따로공유됨 (단일 소스)
일관성노드별 달라질 수 있음단일 소스
적합 데이터불변 (Match, Section, Block)변동 가능 (User, 응답)

2. 분산 락 (Redisson RLock)

SETNX 기반 단순 락에서 Redisson RLock으로 전환했습니다. Watch Dog으로 DB 트랜잭션 지연 시 TTL 자동 갱신, 스레드 ID 기반 소유자 검증, Pub/Sub 기반 효율적 대기 등을 제공합니다.

3. Lua 스크립트 원자 연산 (Phase 4 최적화)

대기열 재진입 시 ZREM + ZADD + ZRANK + ZCARD를 Lua 스크립트로 묶어3 RTT → 1 RTT로 단축했습니다.

-- queue:re-enter atomic script
redis.call('ZREM', KEYS[1], ARGV[1])
redis.call('DEL', KEYS[2])
redis.call('ZADD', KEYS[1], ARGV[2], ARGV[1])
local rank = redis.call('ZRANK', KEYS[1], ARGV[1])
local count = redis.call('ZCARD', KEYS[1])
return {rank, count}

PostgreSQL 테이블 소유권

서비스소유 테이블비고
Auth-Guardusers, user_sns, dev_users, withdrawal_requests회원 관리 (AES-GCM 암호화)
Seatseats, blocks, sections, areas, match_seats, seat_holds, price_policies좌석/가격 구조
Order-Coreorders, order_seats, payments, cash_receipts, cancellation_fee_policies, inquiries주문/결제 (PII 암호화)
공유 (common-core)matches, clubs, stadiums, onboarding_preferences, onboarding_preferred_blocks, onboarding_viewpoint_priority공유 도메인