Skip to content

refactor: ThunderingHerdCaching의 만료 임박 캐시 갱신 정책 수정 #801

Description

@Hexeong

어떤 부분을 리팩터링하려 하나요?

@ThunderingHerdCaching의 만료 임박 캐시 갱신 정책을 리팩터링합니다.

현재 ThunderingHerdCachingAspect.refreshCache()는 캐시 TTL이 임박했을 때 DB에서 값을 재계산하지 않고, 기존 cached value의 TTL만 다시 늘립니다. 이 방식은 hot key에 대한 Thundering Herd 문제를 피하는 효과는 있지만, 트래픽이 계속 있는 경우 stale cache가 TTL을 넘어 장시간 유지될 수 있습니다.

AS-IS

  • 캐시 miss 시에는 create lock을 잡은 요청 1개만 DB를 조회하고 Redis에 저장합니다.
  • 캐시 hit이면서 TTL이 만료 임박한 경우 refresh lock을 잡습니다.
  • refresh lock을 잡은 요청도 DB를 재조회하지 않고 기존 cached value의 TTL만 연장합니다.
  • refresh lock을 잡지 못한 요청은 기존 cached value를 바로 반환합니다.
  • 결과적으로 인기 key는 트래픽이 있는 동안 계속 TTL이 연장되어, 삭제/수정된 데이터가 명시적 evict 전까지 오래 남을 수 있습니다.

TO-BE

  • 캐시 miss 시 동작은 기존처럼 Thundering Herd를 방지합니다.
  • 캐시 hit이면서 TTL이 만료 임박한 경우 refresh lock을 잡은 요청 1개가 DB에서 값을 다시 계산합니다.
  • 새로 계산한 값을 Redis에 저장하고 반환합니다.
  • refresh lock을 잡지 못한 요청은 기존 cached value를 반환해 요청 폭주를 막습니다.
  • TTL은 stale cache의 최대 유지 시간을 의미하도록 동작해야 합니다.

작업 상세 내용

  • ThunderingHerdCachingAspect.refreshCache()가 기존 TTL만 연장하지 않고 값을 재계산하도록 수정
  • refresh lock 획득 실패 시에는 기존 cached value를 반환해 Thundering Herd 방지 유지
  • 캐시 miss/create lock 경로와 refresh lock 경로의 역할을 테스트로 검증
  • 기존 사용처(univApplyInfo:{id}, university:recommend:general:*)에 미치는 영향 확인
  • 필요하면 어노테이션 옵션으로 기존 sliding expiration 동작과 refresh recompute 동작을 분리할지 검토

참고할만한 자료(선택)

관련 PR:

배경:

  • 공통 추천 목록 캐시 개선 중 TTL을 3600초로 낮췄지만, 현재 ThunderingHerdCaching 구현에서는 TTL 임박 시 기존 값을 재계산하지 않고 TTL만 연장합니다.
  • 따라서 트래픽이 계속 있으면 TTL이 stale cache의 최대 유지 시간을 보장하지 못합니다.
  • 이번 작업은 #800의 직접 범위를 넘는 공통 캐시 정책 변경이므로 별도 리팩터링 이슈로 분리합니다.

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions