캐시의 이점과 문제

Amazon에서 수년간 서비스를 구축하면서, 새 서비스가 요청을 처리하기 위해 네트워크 호출을 실행해야 하는 시나리오를 다양하게 경험했습니다. 이 호출은 관계형 데이터베이스, Amazon DynamoDB와 같은 AWS서비스 또는 다른 내부적인 서비스를 대상으로 합니다. 간단한 테스트나 낮은 요청 속도에서는 서비스가 잘 작동하지만 문제가 발생할 수 있음을 알게 되었습니다. 다른 서비스에 대한 이 호출이 느리거나 호출 양이 많아짐에 따라 데이터베이스를 확장하는 비용이 너무 높은 것이 문제였습니다. 또한 많은 요청에 동일한 다운스트림 리소스 또는 동일한 쿼리 결과가 사용되어 이 데이터를 캐싱하는 것이 문제의 해법이 될 수 있다는 사실도 알게 되었습니다. 캐시를 추가하자 서비스가 훨씬 개선되었습니다. 요청 지연 시간이 짧아졌고, 비용이 절감되었으며, 사소한 다운스트림 가용성 저하 현상이 사라졌습니다. 얼마 후에는 캐시를 사용하기 전에 이 같은 문제가 있었다는 사실조차 잊었습니다. 그에 따라 종속 서비스의 플릿 크기가 줄고 데이터베이스는 축소됩니다. 이처럼 아무 문제 없이 잘 작동하는 것처럼 보일 때, 서비스에서 심각한 문제가 발생할 수 있습니다. 트래픽 패턴이 변화하거나, 캐시 플릿에서 장애가 발생하거나, 다른 예기치 않은 상황으로 인해 작동이 멈추거나 캐시를 사용하지 못하게 될 수 있습니다. 그 결과 다운스트림 서비스에 대한 트래픽이 급증하여 종속 서비스와 우리의 서비스 모두에서 가동 중단이 발생할 수 있습니다.

지금까지 캐시에 중독된 서비스를 설명했습니다. 캐시는 우리가 모르는 사이 서비스에 대한 유용한 추가 기능에서 운영에 없어서는 안 될 중요한 부분이 되었습니다. 이 문제의 핵심은 캐시로 인한 모달 동작에 있습니다. 즉, 캐싱되는 객체에 따라 달라지는 동작이 문제입니다. 이 모달 동작의 배포에 있어 예기치 않은 변화는 심각한 문제를 야기할 수 있습니다.

Amazon에서 서비스를 구축하고 운영하면서 캐싱의 이점과 문제점을 모두 경험했습니다. 이 문서의 나머지 부분에서는 그 과정에서 우리가 얻은 교훈, 모범 사례 그리고 캐시 사용에 있어서의 고려 사항을 설명합니다.

캐싱을 사용하는 경우

시스템에 캐시를 추가하게 되는 요인은 몇 가지가 있습니다. 특정 요청 속도에서 관찰되는 종속 서비스의 지연 시간이나 효율성 때문에 캐시 추가를 고려하게 되는 경우가 많습니다. 예를 들어 종속 서비스가 제한 요인이 되기 시작하거나, 예상 로드를 따라가지 못하는 것으로 확인될 때 캐시를 고려할 수 있습니다. 일정하지 않은 요청 패턴으로 인해 핫 키/핫 파티션 조절이 발생할 경우 유용한 해결 방법으로 캐싱을 고려할 수 있습니다. 모든 요청에 걸쳐 캐시의 캐시 적중률이 높을 경우 이 종속 서비스의 데이터는 캐싱하기에 적합한 대상이 됩니다. 즉, 종속 서비스로의 호출 결과를 여러 요청 또는 작업에 사용할 수 있습니다. 각 요청에서 일반적으로 종속 서비스에 대한 고유한 쿼리를 실행해야 하고 요청별로 결과가 고유한 경우 캐시의 적중률이 낮아 캐시를 사용할 이유가 없습니다. 두 번째로 팀의 서비스와 클라이언트가 최종 일관성을 어느 정도나 요구하는지를 고려해야 합니다. 시간이 지나면서 캐싱된 데이터는 소스와 함께 일관되지 않게 증가하기 마련이므로, 서비스와 클라이언트가 그에 대응할 수 있는 경우에만 캐싱이 유용합니다. 원본 데이터의 변경률과 데이터 새로 고침에 대한 캐시 정책에 따라 데이터의 비일관성이 좌우됩니다. 이 두 요인은 서로 연관되어 있습니다. 예를 들어 비교적 정적이거나 변화가 느린 데이터는 더 오랫동안 캐싱할 수 있습니다.

로컬 캐시

서비스 캐시는 메모리 또는 서비스에 대한 외부에서 구현될 수 있습니다. 일반적으로 프로세스 메모리에서 구현되는 온박스 캐시는 비교적 구현이 쉽고 빠르며, 작은 작업에서 상당한 개선 효과를 제공할 수 있습니다. 온박스 캐시는 종종 캐시에 대한 필요성이 확인된 경우 구현 및 평가되는 첫 번째 접근 방식이 됩니다. 외부 캐시와는 반대로, 추가 운영 오버헤드가 없기 때문에 기존 서비스와 통합할 때도 위험성이 꽤 낮습니다. 종종 온박스 캐시를 인 메모리 해시 테이블로 구현합니다. 이는 애플리케이션 논리로 관리하거나(예: 서비스 호출을 완료한 후 명시적으로 결과를 캐시에 배치) 서비스 클라이언트에 포함합니다(예: 캐싱 HTTP 클라이언트 사용).

인 메모리 캐시의 장점과 단순성에도 불구하고, 여러 단점도 수반합니다. 캐싱된 데이터가 플릿의 서버 사이에서 일관되지 않다는 점이 그 하나입니다. 이를 캐시 일관성 문제라고 합니다. 클라이언트가 서비스에 대한 호출을 반복하면 요청을 처리하는 서버에 따라 첫 번째 호출에는 최신 데이터가, 두 번째 호출에는 이전 데이터가 사용될 수 있습니다.

또 다른 단점은 이제 다운스트림 로드가 서비스 플릿 크기에 비례한다는 점입니다. 그래서 서버 수가 늘어나면 종속된 서비스에서도 오버로드가 발생할 수 있습니다. 다운스트림 서비스에 대한 요청 수와 캐시 히트/누락에 대한 지표를 생성하면 이를 효과적으로 모니터링할 수 있다는 점을 깨달았습니다.

인 메모리 캐시도 "콜드 스타트" 문제에 취약합니다. 이 문제는 새 서버가 완전히 빈 캐시로 시작할 때 발생합니다. 이 경우 캐시가 채워지면 종속된 서비스에 대한 요청이 갑자기 늘어날 수 있습니다. 배포 도중이나 캐시가 플릿 전체에서 비워지는 다른 상황에서 큰 문제가 될 수 있습니다. 캐시 일관성 및 빈 캐시 문제는 이 글에서 나중에 자세히 설명할 요청 통합을 사용하여 종종 해결할 수 있습니다.

외부 캐시

외부 캐시는 지금까지 설명한 많은 문제를 해결할 수 있습니다. 외부 캐시는 캐싱된 데이터를 별도의 플릿(예: Memcached 또는 Redis 사용)에 저장합니다. 외부 캐시는 플릿의 모든 서버에 사용되는 값을 유지하므로 일관성 문제가 감소합니다. (캐시를 업데이트할 때 실패하는 경우에 있으므로 이 문제가 완전히 사라지지는 않습니다.) 인 메모리 캐시에 비해 다운스트림 서비스에 대한 전반적인 로드가 감소하며, 로드는 플릿 크기에 비례하지 않습니다. 배포를 진행하는 내내 외부 캐시가 채워진 상태로 유지되므로 배포와 같은 이벤트가 발생하는 동안 콜드 스타트 문제가 나타나지 않습니다. 마지막으로, 외부 캐시는 인 메모리 캐시보다 더 큰 가용 스토리지 공간을 제공하여 공간 제약으로 인한 캐시 제거의 발생 빈도를 줄입니다.

단, 외부 캐시에도 고려해야 할 단점이 있습니다. 첫째, 모니터링하고 관리하고 확장해야 할 플릿이 늘어나는 셈이므로, 전반적인 시스템 복잡성과 운영 로드가 증가합니다. 캐시 역할을 하는 캐시 플릿의 가용성 특성은 해당 대상 종속 서비스의 가용성 특성과 다릅니다 예를 들어 무중단 업그레이드를 지원하지 않고 유지 관리 기간을 필요로 할 경우 캐시 플릿의 가용성이 더 낮을 수 있습니다.

외부 캐시로 인한 서비스 가용성 저하를 방지하려면 캐시 플릿 비가용성, 캐시 노드 장애 또는 캐시 put/get 장애를 처리할 서비스 코드를 추가해야 합니다. 해결 방법 중 하나로 종속 서비스를 호출하는 방식으로 돌아갈 수 있지만, 이 방법을 사용할 때는 주의해야 합니다. 캐시 작동 중단이 길어질 경우 이 방법은 다운스트림 서비스에 대한 트래픽의 이례적 급증을 야기하여 해당 종속 서비스의 제한 또는 부분 정전이 발생하며 궁극적으로 가용성을 떨어뜨립니다. 이보다는 외부 캐시를 사용하지 못할 경우 폴백할 수 있는 인 메모리 캐시를 외부 캐시와 함께 사용하거나, 로드 차단 기능을 사용하고 다운스트림 서비스로 전송되는 요청의 최대 속도를 설정하는 방법이 효과적입니다. 종속 서비스의 부분 정전을 방지하기 위해 적용한 안전 장치가 예상대로 작동하는지 검증하기 위해 캐싱이 비활성화된 상태로 서비스 동작을 테스트합니다.

두 번째 고려 사항은 캐시 플릿의 확장과 탄력성입니다. 캐시 플릿이 요청 속도 또는 메모리 제한에 도달하면 노드를 추가해야 합니다. 모니터와 경보를 설정할 수 있도록 이 같은 제한을 가장 잘 나타내는 지표가 무엇인지 결정해야 합니다. 예를 들어 최근에 작업한 서비스에서 우리 팀은 Redis 요청 속도가 제한에 도달하면서 CPU 사용률이 매우 높아지는 것을 확인했습니다. 이에 실제 트래픽 패턴을 사용한 로드 테스트를 통해 한계를 확인하고 적절한 경보 임계값을 찾았습니다.

캐시 플릿에 용량을 추가할 때는 가동 중단이나 막대한 양의 캐시 데이터 손실이 발생하지 않도록 주의했습니다. 캐싱 기술마다 고유한 고려 사항이 있습니다. 예를 들어 일부 캐시 서버는 가동 중단 없이 클러스터에 노드를 추가하도록 지원하지 않으며, 일관된 해싱을 제공하지 않는 캐시 클라이언트 라이브러리도 있습니다. 이 같은 일관성은 캐시 플릿에 노드를 추가하고 캐싱된 데이터를 재분산하는 데 필요합니다. 일관된 해싱 기능과 캐시 플릿에서 노드를 검색하는 기능의 클라이언트 구현 방식이 다양하기 때문에 프로덕션에 적용하기 전에 캐시 서버를 추가하고 제거하면서 철저하게 테스트합니다.

외부 캐시의 경우 스토리지 형식이 변경되었기 때문에 강력한 성능을 보장할 수 있도록 각별히 주의를 기울입니다. 캐싱된 데이터는 영구 스토어에 저장된 것처럼 처리됩니다. 업데이트된 소프트웨어가 이전 버전 소프트웨어가 기록한 데이터를 읽고, 이전 버전이 새 형식/필드를 정상적으로 인식하고 처리하도록 해야 합니다(예: 플릿에 이전 코드와 새 코드가 함께 사용될 경우 배포 시). 포이즌 필 현상이 발생하지 않게 하려면 예기치 않은 형식이 발생했을 때 포착되지 않는 예외를 방지해야 합니다. 하지만 이것으로 모든 형식 관련 문제를 방지할 수는 없습니다. 버전 형식 불일치를 감지하고 캐싱된 데이터를 폐기하면 캐시의 대량 새로 고침이 발생하여 종속 서비스의 제한 또는 부분 정전으로 이어질 수 있습니다. 직렬화 형식 문제는 배포 중 롤백 안전 보장 문서에서 자세하게 설명합니다.

외부 캐시와 관련한 마지막 고려 사항은 서비스 플릿의 개별 노드에 의해 업데이트된다는 점입니다. 일반적으로 캐시에는 조건부 put 및 트랜잭션과 같은 기능이 없기 때문에 캐시 업데이트 코드가 올바른지, 잘못된 상태 또는 일관되지 않은 상태로 캐시에서 나갈 수 없는지를 주의하여 확인해야 합니다.

인라인 캐시와 사이드 캐시

다양한 캐싱 방식을 평가할 때 결정해야 할 또 다른 사항으로는 인라인 캐시와 사이드 캐시 중에서 선택하는 것입니다. 인라인 캐시 또는 read-through/write-through 캐시는 기본 데이터 액세스 API에 캐시 관리 기능을 내장하여 캐시 관리를 해당 API의 구현 항목 중 하나로 만듭니다. Amazon DynamoDB Accelerator(DAX)와 같은 애플리케이션별 구현과 HTTP 캐싱과 같은 표준 기반 구현을 예로 들 수 있습니다(로컬 캐싱 클라이언트를 사용하거나 Nginx 또는 Varnish 같은 외부 캐시 서버 사용). 반면 사이드 캐시는 Amazon ElastiCache(Memcached 및 Redis)나 Ehcache, Google Guava 등의 라이브러리(인 메모리 캐시의 경우)에서 제공되는 것과 같은 일반 객체 스토어입니다. 사이드 캐시를 사용할 경우 애플리케이션 코드는 데이터 원본을 호출하기 전후에 캐시를 직접 조작하여 캐싱된 객체를 확인한 후 다운스트림 호출을 생성하고 해당 호출을 완료한 후에 객체를 캐시에 넣습니다.

인라인 캐시의 기본적인 이점은 클라이언트의 일관된 API 모델에 있습니다. 즉, 클라이언트 로직을 변경하지 않고 캐싱을 추가, 제거 또는 조정할 수 있습니다. 또한 인라인 캐시는 캐시 관리 로직을 애플리케이션 코드에서 없애 주므로 잠재적으로 버그가 발생할 가능성이 사라지는 셈입니다. 특히 HTTP 캐시는 인 메모리 라이브러리, 앞서 설명한 것과 같은 독립 실행형 HTTP 프록시, CDN(콘텐츠 전송 네트워크)과 같은 관리형 서비스 등 수많은 옵션을 기본적으로 제공하기 때문에 매우 유용합니다.

하지만 인라인 캐시의 투명성은 가용성에 있어서 불리하게 작용할 수 있습니다. 외부 캐시는 이 종속 서비스의 가용성 등식에 있어서 하나의 요인이 되었습니다. 클라이언트가 일시적으로 사용 불가능한 캐시에 대응할 기회가 없습니다. 예를 들어 외부 REST 서비스에서 발생하는 요청을 캐싱하는 Varnish 플릿이 있는 경우 해당 캐싱 플릿이 가동 중지되면 서비스의 관점에서는 종속 서비스 자체가 작동 중단된 것과 같습니다. 인라인 캐시의 또 다른 단점은 캐싱 대상이 되는 프로토콜 또는 서비스에 내장되어야 한다는 점입니다. 프로토콜에 인라인 캐시를 사용할 수 없는 경우, 통합 클라이언트 또는 프록시 서비스를 직접 구축하지 않는 한 이 인라인 캐싱은 옵션이 될 수 없습니다.

캐시 만료

캐시 구현에 있어서 가장 까다로운 부분은 적절한 캐시 크기, 만료 정책, 제거 정책을 선택하는 것입니다. 만료 정책은 캐시에 항목을 보존하는 기간을 결정합니다. 가장 일반적인 정책에서는 절대 시간을 기준으로 한 만료 방식을 사용합니다(즉, 로드되는 각 객체에 TTL(Time to Live) 연결). TTL은 클라이언트에서 얼마나 오래된 데이터가 허용되는지, 데이터가 얼마나 정적인지 등의 클라이언트 요구 사항에 따라 선택됩니다. 변경 속도가 느린 데이터가 더 적극적으로 캐싱될 수 있기 때문입니다. 이상적인 캐시 크기는 요청의 예상 볼륨 및 해당 요청 간의 캐싱된 객체 분산에 대한 모델을 기준으로 합니다. 이를 바탕으로 해당 트래픽 패턴에 대해 높은 캐시 적중률을 보장할 수 있는 캐시 크기를 계산합니다. 제거 정책은 최대 용량에 도달했을 때 캐시에서 항목을 지우는 방식을 제어합니다. 가장 일반적인 제거 정책은 LRU(최소 최근 사용)입니다.

지금까지는 개념적인 연습에 지나지 않습니다. 실제 트래픽 패턴은 이 같은 모델과는 다르므로 캐시의 실제 성능을 추적해야 합니다. 캐시 성능을 추적하는 효과적인 방법은 캐시 적중률과 미적중률, 전체 캐시 크기, 요청 수에 대한 서비스 지표를 다운스트림 서비스로 내보내는 것입니다.

캐시 크기와 만료 정책 값은 신중하게 선택해야 한다는 것을 배웠습니다. 초기 구현 시에 개발자가 캐시 크기와 TTL 값을 독단적으로 선택한 후, 나중에 적절한 값인지 다시 검토하거나 검증하지 않는 상황이 발생해서는 안 됩니다. 이 같은 부주의한 구현 프로세스로 인해 일시적인 서비스 가동 중단이 발생하고 지속적인 가동 중단으로 이어지는 실제 사례를 많이 보았습니다.

다운스트림 서비스가 사용 불가 상태가 되었을 때 복원력을 높이기 위한 다른 패턴으로 두 가지 TTL, 즉 소프트 TTL와 하드 TTL을 사용할 수 있습니다. 클라이언트는 소프트 TTL에 따라 캐싱된 항목을 새로 고치지만, 다운스트림 서비스가 사용 불가 상태가 되거나 요청에 응답하지 않을 경우 하드 TTL에 도달할 때까지 기존 캐시 데이터가 계속 사용됩니다. 이 패턴의 한 예가 AWS Identity and Access Management(IAM) 클라이언트에 사용되었습니다.

또한 배압을 적용한 소프트 및 하드 TTL을 사용하여 다운스트림 서비스 부분 정전의 영향을 줄일 수도 있습니다. 다운스트림 서비스는 부분 정전될 경우 배압 이벤트를 사용하여 응답할 수 있고, 이는 호출하는 서비스가 하드 TTL에 도달할 때까지 캐싱된 데이터를 사용하고 캐시에 없는 데이터에 대해서만 요청을 전송해야 한다는 것을 나타냅니다. 다운스트림 서비스가 배압을 제거할 때까지 이 같은 동작은 계속됩니다. 이 패턴은 업스트림 서비스의 가용성을 유지하면서 다운스트림 서비스가 부분 정전으로부터 복구할 수 있도록 합니다.

기타 고려 사항

다운스트림 서비스에서 오류가 수신되었을 때의 캐시 동작도 중요한 고려 사항 중 하나입니다. 이를 처리하는 방법 중 하나는 마지막으로 캐싱된 정상 값을 사용하여 클라이언트에 응답하는 것입니다. 예를 들어 앞서 설명한 소프트 TTL/하드 TTL 패턴을 활용할 수 있습니다. 다른 옵션으로는 긍정 캐시 항목과 다른 TTL을 사용하여 오류 메시지를 캐싱(즉, “부정 캐시” 사용)하고 오류를 클라이언트로 전파하는 것입니다. 특정 상황에서 어떤 방식을 선택할지는 서비스에 따라 달라지고 클라이언트에 오래된 데이터와 오류 중 어느 것을 제공하는 것이 나은지 평가한 결과에 따라 달라집니다. 어느 방식을 사용하든 오류가 발생했을 때 캐시에 무언가가 들어있어야 한다는 점이 중요합니다. 캐시에 아무 정보도 들어있지 않으면 다운스트림 서비스가 일시적으로 사용 불가 상태가 되거나 특정 요청을 처리할 수 없게 되고(예: 다운스트림 리소스가 삭제된 경우), 업스트림 서비스가 다운스트림 서비스에 막대한 트래픽을 계속 발생시키며, 결국 가동 중단을 발생시키거나 기존의 가동 중단 문제를 악화시키게 됩니다. 부정 응답을 캐싱하지 않아 미적중률과 오류가 증가하는 실제 사례를 많이 봤습니다.

보안도 캐싱의 중요한 측면 중 하나입니다. 서비스에 캐시를 도입할 때 우리는 캐시로 인해 발생할 수 있는 추가적인 보안 위험을 평가하고 해결합니다. 예를 들어 외부 캐싱 플릿에는 직렬화된 데이터의 암호화 기능과 전송 레벨 보안 기능이 부족한 경우가 많습니다. 캐시에 민감한 사용자 정보가 저장되는 경우에 이는 특히 중요합니다. 이 문제는 전송 중 암호화 및 저장된 데이터 암호화를 지원하는 Amazon ElastiCache for Redis를 사용하여 해결할 수 있습니다. 캐시는 다운스트림 프로토콜의 취약성을 악용하여 공격자가 자신이 제어하는 값으로 캐시를 채우는 포이즈닝 공격에도 취약합니다. 해당 값이 캐시에 남아 있는 동안 발생하는 모든 요청에 대해 악성 값이 제공되므로 공격의 영향이 배가됩니다. 마지막 예로, 캐시는 사이드 채널 타이밍 공격에도 취약합니다. 캐싱된 값은 캐싱되지 않은 값보다 빠르게 반환되므로 공격자는 응답 시간을 이용하여 다른 클라이언트 또는 테넌트가 유발하는 요청에 대한 정보를 얻을 수 있습니다.

마지막으로, 많은 수의 클라이언트가 캐시되지 않은 동일한 다운스트림 리소스를 필요로 하는 요청을 거의 동시에 발생시키는 “썬더링 허드” 상황을 고려해야 합니다. 이 문제는 서버가 가동되고 빈 로컬 캐시로 플릿에 조인할 때에도 발생할 수 있습니다. 이 경우 각 서버에서 많은 수의 요청이 다운스트림 종속 서비스로 전달되어 제한/부분 정전이 발생할 수 있습니다. 이 문제를 해결하려면 서버 또는 외부 캐시에서 캐싱되지 않은 리소스에 대해 하나의 요청만 대기하도록 하는 요청 통합을 사용합니다. 일부 캐싱 라이브러리는 요청 통합을 지원하며 일부 외부 인라인 캐시(예: Nginx 또는 Varnish)도 요청 통합을 지원합니다. 또한 기존 캐시에 요청 통합을 구현할 수도 있습니다. 

Amazon 모범 사례 및 고려 사항

이 문서에서는 몇 가지 Amazon 모범 사례를 다루고 캐싱과 관련한 장단점과 위험성을 설명했습니다. 우리 팀이 캐시를 도입할 때 사용하는 Amazon 모범 사례와 고려 사항은 다음과 같이 요약할 수 있습니다.

• 비용, 지연 시간 및/또는 가용성 개선의 측면에서 충분히 타당한 캐시의 합당한 필요성이 있는지 확인합니다. 데이터가 캐싱하기에 적합한지 확인합니다. 즉, 데이터가 여러 클라이언트 요청에 걸쳐 사용되는지 확인합니다. 캐시가 제공하는 가치에 대해 비판적으로 검토하고 캐시로 인해 가중되는 위험성보다 이점이 더 큰지 신중하게 검토합니다.
• 나머지 서비스 플릿 및 인프라와 동일한 엄격한 규칙과 프로세스로 캐시를 운영하도록 계획합니다. 이 작업을 간과해서는 안 됩니다. 캐시 사용률과 적중률에 대한 지표를 내보내 캐시가 적절하게 튜닝되어 있는지 확인합니다. CPU, 메모리 등 주요 지표를 모니터링하여 외부 캐싱 플릿이 정상 상태이고 적절하게 조정되었는지 확인합니다. 이 같은 지표에 대해 경보를 설정합니다. 가동 중단 또는 대량의 캐시 무효화 없이 캐싱 플릿을 확장할 수 있는지 확인합니다(즉, 일관된 해싱이 정상적으로 작동하는지 검증).
• 캐시 크기, 만료 정책, 제거 정책을 경험을 바탕으로 신중하게 선택합니다. 테스트를 수행하고 이전 항목에서 언급한 지표를 사용하여 이 같은 선택을 검증하고 튜닝합니다.
• 캐싱된 데이터를 사용하여 요청을 처리하지 못하는 다양한 상황을 비롯하여, 캐시 가용성 손실이 발생했을 때 서비스 복구가 가능한지 확인합니다. 이 같은 상황에는 콜드 스타트, 캐싱 플릿 가동 중단, 트래픽 패턴 변화 또는 장시간의 다운스트림 가동 중단이 있습니다. 많은 경우에 이러한 문제를 방지하려면 가용성을 일부 포기하여 서버 및 종속 서비스가 부분 정전되지 않게 해야 합니다(예: 로드 차단, 종속 서비스에 대한 요청 수 제한 또는 오래된 데이터 제공). 캐시가 비활성화된 상태로 로드 테스트를 실행하여 이를 검증합니다.
• 암호화, 외부 캐싱 플릿과 통신할 때의 전송 보안, 캐시 포이즈닝 공격 및 사이드 채널 공격의 영향 등 캐싱된 데이터를 유지하는 데 있어서 보안 측면을 고려합니다.
• 시간이 지남에 따라 진화하도록 캐싱된 객체의 스토리지 형식을 설계하고(예: 버전 번호 사용), 이전 버전을 읽을 수 있도록 직렬화 코드를 작성합니다. 캐시 직렬화 로직의 포이즌 필을 주의합니다.
• 캐시가 다운스트림 오류를 어떻게 처리하는지 평가하고 별도의 TTL을 사용하여 네거티브 캐시를 유지하는 방식을 고려합니다. 일부 다운스트림 리소스를 반복적으로 요청하고 오류 응답을 폐기하여 가동 중단을 유발하거나 가중시키지 않도록 합니다.

Amazon 서비스 팀은 캐싱 기술을 많이 사용합니다. 이 기술은 이점이 많지만 단점이 이점보다 큰 경우도 있기 때문에 캐싱 적용 여부는 신중하게 결정합니다. 이 문서가 여러분의 자체 서비스에서 캐싱을 평가하는 데 도움이 되기를 바랍니다.


저자에 대하여

Matt은 Amazon의 이머징 디바이스 수석 엔지니어로서 미래의 소비자 디바이스를 위한 소프트웨어 및 서비스와 관련한 작업을 하고 있습니다. 이전에는 라이브 및 온디맨드 동영상용의 개인화된 서버 측 광고 삽입 서비스인 MediaTailor를 출시한 유능한 팀인 AWS Elemental에서 근무했습니다. 이후 Matt은 NFL Thursday Night Football을 스트리밍하는 PrimeVideo의 첫 번째 시즌을 발표하는 데 도움을 주었습니다. Amazon 입사 전 Matt은 15년간 보안 업계에 몸담으며, McAfee, 인텔, 몇몇 스타트업 기업에서 엔터프라이즈 보안 관리, 맬웨어 방지 및 익스플로잇 방지 기술, 하드웨어 지원 보안 기술, DRM 등을 담당했습니다.

Jas Chhabra는 AWS의 수석 엔지니어입니다. Jas는 2016년에 AWS에 합류했으며 2년여 동안 AWS IAM 작업을 한 후 현재의 AWS Machine Learning 관련 역할을 맡게 되었습니다. AWS 입사 전에는 인텔에서 IoT, 자격 증명, 보안 분야의 다양한 기술 업무를 담당했습니다. 현재는 기계 학습, 보안 및 대규모 분산 시스템에 큰 관심을 보이고 있습니다. 이전에는 IoT, 비트코인, 자격 증명, 암호화 등이 관심 분야였습니다. Jas는 컴퓨터 과학 석사입니다.

분산 시스템의 폴백 방지 오버로드를 방지하기 위해 로드 차단 사용 배포 중 롤백 안전 보장