Skip to content

[refactor][queue-service] Sorted Set score 에 tie-breaker 도입 (동시 진입 FIFO 보장) #9

@coderabbitai

Description

@coderabbitai

📌 개요

현재 Sorted Set 의 score 가 단순 epoch milli. 같은 millisecond 에 여러 토큰 발급 시 score 동일 → Redis 가 멤버 문자열 (UUID) 사전순으로 정렬 → 실제 발급 순서와 어긋난다.

티켓 예매 같은 초고동시성 환경에서 동시 진입자가 다수 발생 시 대기열 순서가 비결정적이 되어 사용자 경험 / 공정성에 영향을 준다.

🎯 목표

  • 동시 진입자도 결정론적 FIFO 순서 보장
  • findRank, findAdmissionCandidates 결과 일관성 확보
  • 운영 시 대기열 공정성 강화

🧩 리팩토링 범위

  • 클래스 / 패키지 구조 개선
  • 메서드 분리 / 네이밍 개선 (score 계산 로직 추가)
  • 중복 로직 제거
  • 트랜잭션 / 예외 처리 정리

🏗️ 변경 설계

변경 전 구조

long issuedAtEpochMilli = token.getIssuedAt().toEpochMilli();
operations.opsForZSet().add(programKey, tokenIdStr, issuedAtEpochMilli);

→ 동일 ms 시 score 충돌 → 사전순 정렬

변경 후 구조

중간 단계 — INCR 시퀀스 추가

long counter = redisTemplate.opsForValue().increment("queue:seq:" + programId);
double score = epochMilli * 1_000_000.0 + counter;
operations.opsForZSet().add(programKey, tokenIdStr, score);
  • 단조 증가 시퀀스로 결정론적 순서 보장
  • 비교적 간단한 변경

최종 단계 — Lua Script tie-breaker

영향 받는 기능

  • enqueue() — score 계산 로직 변경
  • findRank() — 정확한 순번 반환
  • findAdmissionCandidates() — 정확한 FIFO 순서

⚠️ 주의 사항

  • 기능 동작은 기존과 동일 (순서 정확성만 ↑)
  • API 스펙 변경 없음
  • 시퀀스 키 (queue:seq:{programId}) 추가 — 메모리 사용 증가 미미
  • 시퀀스 오버플로우 방지 (long 범위 내 충분, 우려 시 주기 리셋 검토)

🧪 검증 방법

  • 기존 테스트 통과 여부 확인
  • 동시 진입 테스트 추가 (같은 ms 발급 시 발급 순서 검증)

🔗 참고

Metadata

Metadata

Assignees

Labels

No fields configured for Feature.

Projects

Status
Done

Relationships

None yet

Development

No branches or pull requests

Issue actions