배경

우리 서비스에서는 주기적으로 앱 사용자들에게 큐레이팅 정보로 랜딩되는 푸시알림을 보낸다. 얼마 전부터 앱푸시 열람수가 많은 경우에 서버장애가 발생하여, 원인을 파악하고 개선했던 경험을 정리해보았다.

 

우선 AWS RDS 성능개선도우미에서 AAS 가 높은 SQL을 조회해보았다. 이상한 점은 기존에 레디스 캐싱이 ttl: N분으로 적용되어있음에도 호출 수가 수백여 건인 것이었다. 캐싱이 만료된 시점에 거의 동시에 요청이 몰려 캐싱이 되기 전에 캐시 값을 계산하기 위한 로직이 요청 수 만큼 실행된 것으로 예상되었다.

 

본론

이 문제를 방지하기 위한 두 가지 전략을 사용하였다.

 

첫 번째는 확률적 재계산으로, ttl이 N분으로 설정한 경우 캐시가 만료되기 M(M<N)분 전부터 임의의 확률로

  • 기존이 캐싱값을 가져가거나
  • 재계산 후 해당 값을 캐싱하는 것이다. 

이렇게 하면 M분 이후에 요청이 몰리더라도 (확률에 따라) 캐시값을 계산하기 위한 로직의 실행 횟수를 요청수보다 적게 가져갈 수 있다.

단점은 백그라운드에서 실행되는 게 아니라 클라이언트의 요청이 발생해야 적용되는 것인데, 이번 작업의 경우 아주 빈번하게 요청되는 API였기에 문제가 되지 않았다.

 

 

두 번째는 레디스 분산락이다. 캐시값을 계산하기 전 레디스로부터 락 획득을 시도하여,

  • 성공한 경우에만 계산 후 캐싱을 하고, 락을 해제한다. 
  • 실패한 경우에는 일정 시간동안 대기하여 캐시값을 다시 가져간다.

이번 작업의 경우에는 일정 시간 후에도 캐시값이 없는 경우에 오류를 발생시키거나 유효하지 않은 데이터를 응답할 수 없었기에, 일정 시간 후에는 결국 재계산을 하도록 구현했다.

 

 

위 작업을 통해 앱 푸시가 발송된 후에도 안정적으로 운영되는 것을 확인했다.

 

 

+ Recent posts