대부분의 중단은 데이터베이스에서 시작되지 않습니다. 캐시에서 시작합니다.

대부분의 중단은 데이터베이스에서 시작되지 않습니다. 캐시에서 시작합니다.

컴퓨터 과학에는 두 가지 단단한 것들이 있습니다 : 캐시 무효화 및 이름 지정 – Phil Karlton

캐싱은 시스템 설계에서 중요한 기술이며 몇 가지 이점을 제공합니다. 캐싱을 사용하면 시스템의 성능 및 가용성을 향상시키면서 서비스 운영 비용을 동시에 줄일 수 있습니다. 캐싱은 시스템 설계의 스위스 군대 나이프입니다.

이 기사에서는 주로 시스템 설계의 다른 측면에 간접적으로 도움이되는 가용성과 탄력성에 대해 이야기 할 것입니다. 예를 들어, 캐시를 통해 주로 사용자 요청을 제공하는 서비스는 백엔드 시스템에 대한 통화 수를 줄일 수 있으며, 이는 서비스를 실행하기 위해 발생하는 주요 비용 소스 중 하나입니다. 마찬가지로, 캐시가 고객 요청에 신속하게 제공 될 수 있으므로 서비스는 초당 높은 요청 비율 (RPS)을 지원할 수 있습니다. 이뿐만 아니라 서비스가 캐시 된 데이터를 통해 요청을 제공 할 수 있다면 다운 스트림 의존성에 대한 압력을 줄이고 실패하거나 브라우닝하지 않아 서비스를 사용하는 데 도움이됩니다.

그러나 그 말이 진행됨에 따라이 세상에는 무료 점심이 없습니다. 캐시에는 단점도 함께 제공됩니다. 캐시의 성능은 일반적으로 캐시 히트 또는 미스 형태로 측정됩니다. 캐시 히트 비율이 높은 한 모든 것이 예상대로 완벽하게 작동합니다. 비교적 높은 비율의 캐시 미스를보기 시작하면 단점이보기 시작합니다. 예를 들어, 서비스는 1K TPS 만 수행 할 수있는 서비스를 구축 한 초당 10K 트랜잭션 (TPS)에 서비스를 제공 할 수 있습니다. 좋은 날에는 문제가 없으며 최대 10%의 실패율을 견딜 수 있습니다. 그러나 나쁜 날에는 어떤 이유로 요청의> 10%가 캐시에서 데이터를 얻지 못하면 서비스로 전화를 걸고 브랜딩 위험을 감수 할 위험이 있습니다. 이제 서비스가 복구하는 데 시간이 걸리면 지금 당장 좋은 항목도 은퇴하고 캐시가 누락되어 백엔드 서비스로의 트래픽이 추가로 증가합니다. 재 시도 딜레마와 배압에 관한 마지막 두 기사에서, 나는 적절한 가드 레일이 제자리에 있지 않으면 행동의 약간의 변화가 어떻게 길쭉한 정전으로 이어지는 지에 대해 이야기했습니다. 마찬가지로 캐시에는 가드 레일과 신중한 고려가 필요합니다.

이러한 것들을 피하기 위해 수행 할 수있는 작업에 대한 세부 사항을 살펴보기 전에 일반적인 캐시 실패 모드를 보자.

실패 모드

계단식 실패 : Doom 루프

일단 시작되면 완전한 정전이 발생할 수 있기 때문에 이것을 Doom 루프라고 부릅니다. 설명하겠습니다. 일반적으로 캐시는 여러 캐시 노드로 구성되어로드를 배포합니다. 한 노드가 실패하면 새 노드가 나타나고 트래픽을 시작하는 동안로드가 다른 노드로 이동합니다. 이제 캐시 클러스터의 모든 노드가 뜨거워지고 하나의 노드가 실패하는 시나리오를 상상해보십시오. 실패한 노드의 트래픽이 클러스터의 다른 노드로 유출되어 과부하가 걸려 결국 충돌합니다. 더 많은 노드가 클러스터에서 나오면 부하가 나머지 건강한 노드로 이동하여 잠재적으로 완전한 정전으로 이어집니다. 이런 종류의 정전은 실제 세계에서 들어 본 적이 없으며 발생했습니다. 하나의 노드가 제거 된 다음 클러스터에 다시 구분되는 간단한 배치조차도 이러한 종류의 정전을 유발할 수 있습니다.

천둥 무리 : 과도한 백엔드 하중 생성

이것은 캐시 및 실패 모드를 논의 할 때 종종 볼 수있는 또 다른 캐시 실패 시나리오입니다. 뉴스 기사와 같이 많은 사용자가 동일한 정보에 액세스하는 인기있는 웹 사이트를 고려하십시오. 이 기사는 종종 검색 시간을 가속화하기 위해 캐시에 저장됩니다. 모든 것이 예상대로 작동하지 않을 때까지 작동합니다. 캐시 항목이 수천 명의 사람들에게 성공적으로 서비스를 제공하고 있다고 가정 해 봅시다. 그러나 만료에 도달한다고 가정 해 봅시다. 갑자기, 이러한 모든 사용자는 이제 쿼리를 제공하기 위해 데이터베이스로 전송됩니다. 이로 인해 백엔드에 과부하가 발생하여 속도가 느려지고 오류 및 완전한 충돌이 발생합니다. 이것은 일반적으로 천둥 무리 문제로 알려져 있습니다. 백엔드의 부하가 증가하면 올바르게 행동하는 모든 것에 의존하는 다른 종속 서비스에 대한 계단식 실패로 이어질 수 있습니다.

캐시 일관성 : 캐시의 일관되지 않은 데이터

대규모 시스템에서 캐시는 종종 사용자 요청을 제공하기 위해 L1 (Memory) 및 L2 (소스 데이터베이스)와 같은 여러 노드 및 레벨에 분산됩니다. 그러나 주어진 사용자에 대해 이러한 노드의 일관성을 유지하는 것은 다양한 액세스 패턴 및 데이터 요구 사항으로 인해 어려울 수 있습니다. 자주 변경되는 데이터와 같은 부적절한 데이터를 캐싱하면 캐싱의 이점을 무효화하고 오버 헤드가 증가하고 캐시가 누락됩니다. 이로 인해 다른 노드를 사용하여 다른 응용 프로그램이 처리하고 일관되지 않은 결과를 생성하는 신뢰할 수없는 동작이 발생할 수 있습니다.

Forever Caches : 캐시 항목을 퇴치하고 무효화/만료합니다

캐싱 이야기는 캐시 퇴거와 무효화에 대해 논의하지 않고 불완전합니다. 캐시에서 항목을 제거하는 것은 추가하는 것만 큼 중요합니다. 일반적인 캐시 퇴거 기술에는 최근에 사용되지 않은 (LRU), 가장 자주 사용되는 (LFU) 및 FIFO가 포함됩니다. 캐시 퇴거는 일반적으로 캐시가 용량 일 때 발생합니다. 그러나 캐시가 가득 찬 시나리오를 고려하고 자주 사용되는 데이터 포인트를 제거하십시오. 이 제거는 캐시 미스로 이어지고 천둥 무리 효과를 통해 성능 회귀를 유발합니다. 또 다른 가능성은 선택된 정책과의 충돌로 인해 동일한 데이터가 반복적으로 추가되고 제거되어 캐시 성능 저하로 이어지는 스 래싱입니다.

반면에 데이터가 오래되면 무효화가 필요합니다. 일반적인 무효화 기술은 시간 기반 또는 이벤트 중심 만료입니다.

무효화로 인한 일반적인 실패는 부적절하게 구현 될 때 발생하여 서비스 중단으로 이어집니다. 예를 들어, 캐시 입력 제거 (만료 또는 퇴거)를 구현하지 않은 경우 캐시가 크기가 커지고 결국 캐시 노드가 충돌합니다. 이것은 백엔드뿐만 아니라 다른 캐시 노드의 부하를 증가시켜 위에서 설명한 DOOM 루프를 트리거 할 수 있습니다. 사람들은 종종 캐시를 구현할 때 이것을 잊어 버립니다. 나는이 행동이 발견되기 전에 생산 시스템이 수년 동안 작동하여 다 시간이 중단되는 것을 보았다. 누군가가 적절하게 말했듯이, “모든 것이 이유가 있습니다.”

이것이 유일한 캐시 실패 모드는 아니라고 확신하지만 지금은 이것에 집중하고 싶습니다. 이러한 실패 모드를 해결하고 캐시를 대량 생산 사용 사례에 유용하게 만드는 몇 가지 실용적인 전략에 대해 논의 해 봅시다.

실용적인 접근

중간체 캐시 : L2 캐싱 층

캐시의 경우 두 개가 하나보다 낫습니다. 아이디어는 인 메모리와 백엔드 데이터베이스 사이에 중간 계층을 소개하는 것입니다. 이 중간 캐시는 이용 가능하고 백엔드 데이터베이스에서 분리됩니다. 캐시 미스가 발생하면 먼저이 중간 계층을 확인하고 (L2라고합시다) 데이터가없는 경우에만 L3 (백엔드)에 도달합니다. 이는 응용 프로그램과 백엔드 데이터베이스 간의 직접 커플 링을 제거하고 배포를 단순화합니다. 캐시 노드 퇴거가 발생하면 백엔드 자체 대신 L2로 돌아갑니다. 이것은 기본 응용 프로그램과 별개이므로 더 나은 성능을 위해 전용 설정과 더 편안한 메모리 제약 조건을 가질 수 있습니다.

그러나 지금 볼 수 있듯이 새로운 캐싱 함대가 유지됩니다. 이로 인해 비용이 증가하고 시스템은 이제 새로운 운영 모드를 다루고 있습니다. 이전 기사에 언급 된 모든 모범 사례는 여기에서 실패를 처리 할 때 고려해야합니다.

Coalescing을 요청합니다

이전 섹션에서는 L2 캐싱 층을 소개하는 것에 대해 논의했습니다. 도움이 되더라도 여전히 천둥 무리 문제로 고통받을 수 있으며 과부하를 방지하기 위해 보호 수단이 필요합니다. 캐시를 사용하는 응용 프로그램은이를 완화하는 데 도움이 될 수 있습니다. 응용 프로그램 코드는 요청 Coalescing이라는 기술을 사용할 수 있으며, 여기서 여러 유사한 요청이 결합되어 백엔드 압력을 줄입니다. 이 기술에서는 유사한 요청 중 하나만 작성되며 반환 된 데이터는 모든 공통 통화와 공유됩니다.

요청 연합을 구현하는 방법에는 여러 가지가 있습니다. 인기있는 접근 방식 중 하나는 요청이 준비되는 대기열을 소개하는 것입니다. 단일 프로세서 스레드는 백엔드 호출을하고 모든 대기 요청에 대한 응답을 배포하는 것입니다. 잠금은 또 다른 널리 채택 된 기술입니다.

현명한 캐싱

캐싱 솔루션의 성공은 캐시 적중률로 측정됩니다. 성공 가능성을 높이려면 자주 액세스하는 데이터 또는 읽기 대 읽기 비율이 높은 데이터로 캐시를 미리 따뜻하게 할 수 있습니다. 이것은 백엔드의 부하를 줄이고 일반적으로 콜드 캐시 문제에 대한 솔루션이라고합니다. 또 다른 유용한 기술은 백엔드 데이터베이스에없는 데이터를 캐시하고 응용 프로그램 코드를 업데이트하여 처리하는 네거티브 캐싱입니다. 이 경우 캐시 나 백엔드에없는 특정 레코드에 대한 데이터를 가져 오도록 쿼리가 만들어지면 백엔드를 쿼리하지 않고 “데이터 없음”응답으로 제공 될 수 있습니다. 또한 “쓰기 캐시”, “쓰기 백 캐시”및 “읽기 스루 캐시”와 같은 잘 연구 된 캐싱 전략은 응용 프로그램의 요구에 따라 고려해야합니다.

적절한 캐시 퇴거 및 무효화/만료

수행자 캐시의 핵심은 퇴거 및 기록 무효화가 처리되는 방법입니다. 올바른 캐시 크기를 유지하려면 퇴거가 필요합니다. 퇴거 정책은 용량에 도달 할 때 캐시에서 어떤 항목을 제거할지 결정합니다. 예를 들어, 시간적 위치가 중요한 경우 LRU를 사용하십시오. 일관된 액세스 패턴이있는 경우 LFU를 사용하십시오.

무효화/만료는 캐시를 메모리에 얼마나 오래 유지하는지 결정합니다. 만료를 설정하는 가장 일반적인 기술은 절대 시간 기반 만료 (TTL)를 통한 것입니다. 적절한 TTL을 설정하는 것은 핫키의 퇴거 또는 퇴거를 피하기 위해 중요합니다. 동시 퇴거를 피하기 위해 TTL을 지터로 지정할 수 있습니다. 일반적으로 TTL은 응용 프로그램의 의존성 감도에 따라 설정됩니다.

준비는 필수적이지만 실제 데이터와 비교하는 것은 없습니다. 합리적인 설정으로 시작한 다음 메트릭 및 알람을 사용하여 캐시 성능을 측정하고 생산 요구에 맞게 조정하십시오.

캐시는 실패합니다.

캐시 고장이 발생한 후에 만 ​​준비하는 대신 설계 자체로 고장 완화를 굽겠습니다. 캐시가 결국 실패한다는 가정으로 시작할 수 있으며 시스템은이를 처리 할 수 ​​있어야합니다. 위에서 설명한 천둥 무리 시나리오를 예로 들어 봅시다. 준비하기 위해 개발자는 캐시 쿼리 요청에 ~ 10% (또는 적절한) 고장 속도를 도입하고 시스템의 동작 방식을 관찰하는 것이 좋습니다. 규칙적인 간격으로이를 발생시키고 시스템 이이 고장 모드를 운동하게하는 것은 카나리아 일 수 있습니다. 이것은 천둥 무리와 Doom 루프 고장 모드를 강조하는 데 도움이됩니다. 이것은 종종 간과되며 개발자 도구 세트에서 가장 강력한 도구입니다. 캐시 모니터링 : 정기적으로 캐시 성능을 분석하고 전략을 변경하여보다 역동적으로 만듭니다.

결론

캐싱은 분산 시스템에 필요한 성능과 확장 성을 가져올 수 있지만 비판적 사고 및 전략 계획이 필요합니다. 캐싱의 잠재적 인 함정을 이해하면 개발자가 시스템을 효과적으로 최적화하면서 위험을 줄일 수 있습니다. 전략적 캐싱, 강력한 무효화, 일관성 메커니즘 및 포괄적 인 모니터링을 구현함으로써 개발자는 진정으로 효율적이고 탄력적 인 분산 시스템을 만들 수 있습니다.

출처 참조

Post Comment

당신은 놓쳤을 수도 있습니다