Redis 지연 시간 스파이크와 99퍼센타일
원문은 Salvatore Sanfilippo님이 에 게재했습니다. 이 블로그 구독하기
Stripe의 Redis 관련 블로그 포스트에서 흥미로운 점 중 하나는 테스트 과정에서 얻은 지연 시간 그래프를 함께 공개했다는 것이다. Redis가 데이터를 디스크에 영속화하려면 fork() 시스템 콜을 호출해야 한다. 보통 물리 서버나 대부분의 하이퍼바이저에서는 프로세스 크기가 커도 fork가 빠르다. 하지만 Xen은 fork가 느리기 때문에, 특정 EC2 인스턴스 타입(그리고 다른 가상 서버 제공 업체에서도 마찬가지)에서는 부모 프로세스가 디스크 영속화를 위해 fork할 때마다 심각한 지연 시간 스파이크가 발생할 수 있다. 이 점에서 Stripe이 공개한 그래프는 매우 명확하다.

짐작할 수 있듯이, fork가 진행되는 동안 지연 시간 테스트를 수행하면 부모 프로세스가 fork되는 순간에 걸친 모든 요청은 최대 1초까지 지연된다(위 그래프를 예로 들면 그렇다는 것이며, 프로세스 크기나 EC2 인스턴스가 무엇이었는지는 정확히 알 수 없다). 이로 인해 높은 지연 시간을 기록한 샘플이 다수 발생하고, 이는 99퍼센타일 결과에 영향을 미치게 된다.
이러한 동작을 개선하기 위해 인스턴스 타입이나 설정, 구성 등을 변경하는 것은 좋은 생각이며, 단 하나의 요청이라도 지연 시간이 너무 길어지는 것 자체가 허용되지 않는 사용 사례도 있다. 하지만 30분에 한 번씩 1초간 발생하는 지연 시간 스파이크(혹은 AOF를 적절한 rewrite 트리거와 함께 사용한다면 그보다 더 드물게 발생하는 스파이크)가 요청 집합 전체에 고르게 분포된 지연 시간 스파이크와는 매우 다르다는 점은 언뜻 명확해 보이지 않는 것 같다.
스파이크가 고르게 분포된 경우, 페이지 생성을 위해 Redis 서버에 여러 번 요청해야 한다면 페이지 뷰 하나가 지연 시간 패널티를 겪을 가능성이 매우 높다. 이는 서비스 품질에 잠재적으로 큰 영향을 미칠 수 있다. 다음 링크를 확인해 보라: http://latencytipoftheday.blogspot.it/2014/06/latencytipoftheday-most-page-loads.html.
하지만 30분마다 1초씩 발생하는 지연 시간은 완전히 다른 이야기다. 첫째, 요청 수가 늘어날수록* 양호한 지연 시간을 보이는 퍼센타일은 더 좋아진다. 요청이 많을수록 이 1초간의 지연이 샘플에서 과대 대표될 가능성이 낮아지기 때문이다(만약 1분에 1번만 요청하는데 그 중 하나가 높은 지연 시간에 걸린다면, 초당 100번 요청하는 경우보다 99.99퍼센타일에 훨씬 더 큰 영향을 미치게 된다).
둘째, 대부분의 페이지 뷰는 영향을 받지 않는다. 1초의 지연을 겪는 사용자는 fork 호출 시점에 걸쳐 요청을 보낸 경우뿐이다. 그 외의 모든 요청은 평균 지연 시간보다 현저히 나쁜 지연 시간을 겪을 확률이 극히 낮다. 또한 fork 시점에 걸친 페이지 뷰는 100개의 요청으로 구성되어 있더라도 1초 이상 지연될 수 없다는 점도 기억해야 한다. fork() 호출이 끝나면 요청들이 바로 완료되기 때문이다.
결론적으로, 모든 단일 요청에 대해 엄격한 지연 시간 요구사항이 있다면 가끔 요청이 1초씩 지연될 수 있는 설정은 분명 큰 문제가 된다. 하지만 목표가 양호한 서비스 품질을 제공하는 것이라면, 지연 시간 스파이크의 분포가 결과에 엄청난 영향을 미친다. Xen에서 fork로 인해 발생하는 Redis 지연 시간 스파이크는 시간 축 위에 고립된 점들에 불과하므로, 페이지 뷰가 다수의 Redis 요청으로 구성되어 있더라도 영향을 받는 페이지 뷰의 비율은 지연 시간 스파이크가 차지하는 전체 시간 비율에 비례한다. 이 경우 1800초마다 1초이므로, 영향을 받는 페이지 뷰는 0.05%에 불과하다.
지연 시간 특성을 단일 지표 하나로 포착하기는 어렵다. 전체 퍼센타일 곡선과 스파이크의 분포를 함께 봐야 더 정확한 그림을 얻을 수 있다. 일반적으로 경험칙은 연구를 시작하는 좋은 방법이며, 평균 지연 시간이 빈약한 지표라는 것은 대체로 사실이다. 하지만 경험칙을 절대적인 진리로 격상시키는 것 역시 단점이 있다. 많은 복잡한 것들은 여전히 복잡하며, 우리가 아무리 단순화하고 싶어도 면밀한 검토가 필요하기 때문이다.
동시에, EC2 인스턴스에서의 fork 지연은 오늘날 가장 인기 있는 실행 환경 중 하나에서 Redis 사용자가 겪을 수 있는 최악의 경험 중 하나이므로, 이제 EC2에서 Redis를 정기적으로 테스트하기 시작했다. 곧 Redis 공식 문서에 EC2 전용 최적화 페이지를 추가하고, 영속화를 비활성화한 채 마스터-슬레이브 복제본을 더 안전하게 운영하는 방법을 제공할 예정이다.
지금 당장 EC2에서 영속화를 비활성화한 Redis 마스터가 필요하다면, 가장 간단한 “임시 해결책”은 Redis 인스턴스의 자동 재시작을 비활성화하고 페일오버를 위해 Sentinel을 사용하는 것이다. 이렇게 하면 크래시가 발생한 마스터가 자동으로 다시 살아나지 않고 Sentinel에 의해 페일오버된다. 시스템 관리자는 페일오버가 성공적으로 이루어져 새로운 활성 마스터가 생겼는지 확인한 뒤 마스터를 수동으로 재시작하면 된다.
수정: EC2, Xen 및 fork 시간에 대한 흥미로운 정보가 담긴 Hacker News 스레드를 꼭 확인해 보라: https://news.ycombinator.com/item?id=8532851. 또한 모든 EC2 인스턴스가 동일한 것은 아니며, 특정 타입은 베어메탈 시스템에 버금가는 훌륭한 fork 시간을 제공한다: https://redislabs.com/blog/testing-fork-time-on-awsxen-infrastructure#.VFJQ-JPF8yF
글을 무작위로 읽기
댓글
로그인하고 댓글 남기기