포스트

2024-01-19-TIL

2024-01-19-TIL

Today I Learned

Retry with Backoff Pattern

원격 호출은 네트워크 단절, 일시적인 서비스 불가, 스로틀링(429) 같은 일시적 오류로 실패할 수 있다. 이런 오류는 잠시 뒤 다시 시도하면 성공하는 경우가 많아서, 실패한 호출을 자동으로 재시도하는 것이 Retry 패턴이다. 문제는 실패 직후 같은 간격으로 계속 재시도하면 이미 힘든 서버에 부하를 더 얹는다는 점이다. 그래서 재시도 간격을 점점 늘리는 backoff를 함께 쓴다.

backoff 전략은 대략 세 가지로 나뉜다.

  • Fixed: 매번 같은 간격으로 재시도한다.
  • Linear: 간격을 일정량씩 늘린다.
  • Exponential: 간격을 base * 2^attempt처럼 지수적으로 늘리고, 상한(cap)을 둔다.

지수 backoff만 쓰면 같은 시점에 실패한 클라이언트들이 같은 시점에 다시 몰려 재시도하는 문제가 남는다. 여기에 무작위 값(jitter)을 섞어 재시도 시점을 흩뜨린다. AWS 아키텍처 블로그의 Exponential Backoff And Jitter는 sleep = random(0, min(cap, base * 2^attempt)) 형태의 Full Jitter가 시뮬레이션에서 전체 작업량을 가장 적게 쓴다고 정리한다. Resilience4j에서는 IntervalFunction.ofExponentialRandomBackoff로 지수 backoff와 무작위 간격을 함께 설정할 수 있다.

AWS Prescriptive Guidance는 이 패턴을 쓸 때의 주의점으로 다음을 든다.

  • 재시도 대상 연산은 멱등해야 한다. 그렇지 않으면 부분 반영된 요청이 중복 실행되어 상태가 꼬인다.
  • 재시도가 많아지면 네트워크 대역폭을 차지해 오히려 응답이 느려진다.
  • 일시적이지 않은 오류는 재시도하지 말고 Circuit Breaker로 빨리 실패시키는 편이 낫다.
  • backoff 시간만큼 사용자가 기다리게 되므로 전체 타임아웃과 함께 설계해야 한다.

Redis Delete Key by TTL

Redis의 Key는 TTL을 걸어서 만료되면 -2(만료) 상태가 되고 DELETE 명령어를 실행했을때와 동일하게 최종적으로는 Key가 삭제된다. 하지만 TTL을 걸어놓고 SET한게 아니라면 -1(만료기한 없음)으로 설정된다.

공식 문서 기준으로 정확히 말하면 TTL 명령의 반환값은 다음과 같다. Redis 2.8부터 이렇게 구분되며, 2.6 이하에서는 두 경우 모두 -1이었다.

반환값의미
양수남은 만료 시간(초)
-1키는 있지만 만료 시간이 없음
-2키가 존재하지 않음

즉 -2는 “만료 상태”라는 별도의 값이 아니라, 만료되어 이미 삭제된 키와 처음부터 없던 키를 똑같이 “없는 키”로 보고하는 값이다.

만료와 관련해 알아 둘 동작은 다음과 같다.

  • EXPIRE로 건 만료는 DEL, SET, GETSET처럼 값을 지우거나 덮어쓰는 명령으로만 사라진다. 옵션 없이 SET으로 다시 쓰면 만료가 제거되어 TTL이 -1이 된다. 반면 INCR, LPUSH, HSET처럼 값을 변경만 하는 명령은 만료를 유지한다.
  • PERSIST로 만료를 명시적으로 제거할 수 있다.
  • 0 이하의 시간으로 EXPIRE를 호출하면 키는 만료가 아니라 삭제된다.
  • Redis는 두 가지 방식으로 만료 키를 지운다. 클라이언트가 접근했을 때 만료를 확인해 지우는 passive 방식과, 주기적으로 만료 시간이 있는 키 중 일부를 무작위로 골라 검사하는 active 방식이다. 그래서 만료 시각이 지난 키가 메모리에서 즉시 사라진다고 보장되지는 않지만, 접근하면 항상 없는 키로 보인다.
  • Redis 7.0부터 EXPIRE에 NX, XX, GT, LT 옵션이 생겨, 만료가 없을 때만 설정하거나 더 길어질 때만 갱신하는 식의 조건을 줄 수 있다.
1
2
3
4
5
6
7
8
9
10
> SET mykey "Hello"
OK
> EXPIRE mykey 10
(integer) 1
> TTL mykey
(integer) 10
> SET mykey "Hello World"
OK
> TTL mykey
(integer) -1

로그인 토큰처럼 일정 시간 뒤 자동으로 사라져야 하는 데이터를 저장할 때 TTL이 유용하다. 토큰마다 키를 따로 두면 각자 다른 만료를 줄 수 있다.

참고한 자료외부 출처 10

외부 출처

이 글은 저작권자의 CC BY 4.0 라이선스를 따릅니다.

댓글

아직 댓글이 없습니다