캐시 (Cache)
- 자주 사용하는 데이터나 값을 미리 복사해 놓는 임시 저장소
- 저장 공간이 작고 비용이 비싼 대신 빠른 성능을 제공한다.
- 아래와 같은 경우에 사용을 고려하면 좋다.
- 접근 시간에 비해 원래 데이터를 접근하는 시간이 오래 걸리는 경우 (서버의 균일한 API 데이터)
- 반복적으로 동일한 결과를 돌려주는 경우 (이미지나 썸네일 등)
- 캐시에 데이터를 미리 복사해 놓으면 계산이나 접근 시간 없이 더 빠른 속도로 데이터에 접근할 수 있다.
- 반복적으로 데이터를 불러오는 경우에, 지속적으로 DB 혹은 서버에 요청하는 것이 아니라 Memory 에 데이터를 저장하였다가 불러다 쓰는 것을 의미한다.
- 캐시를 효과적으로 사용하면 시스템의 응답 시간을 줄이고, 서버의 부하를 줄일 수 있다. 이는 사용자 경험을 향상시키고, 시스템의 안정성을 높이는 데 기여한다.
- 리소스에 대한 중복 요청을 막거나 바뀌지 않는 데이터를 새로 불러오는 비용을 줄이기 위해 사용된다.
- 네트워크 대역폭 사용을 줄이고 빠르게 사용자에게 전달하는 목적을 가지고 있다.
- Cache Hit : 원하는 데이터가 캐시에 존재할 경우 해당 데이터를 반환하는 상황
- Cache Miss : 원하는 데이터가 캐시에 존재하지 않을 경우 DB 또는 서버에 요청을 해야하는 상황
- 캐시는 저장공간이 작기 때문에, 지속적으로 Cache Miss 가 발생하는 데이터의 경우 캐싱 전략에 따라서 저장 중인 데이터를 변경해야 한다.
캐시의 필요성
- 파레토 법칙은 전체 결과의 80%가 전체 원인의 20%에서 일어나는 현상을 가리킨다.
- 모든 결과를 캐싱할 필요는 없으며, 서비스 제공 시 자주 사용되는 20%의 데이터만 캐싱한다면 전체적으로 효율을 극대화할 수 있다는 의미이다.
- 이 때문에 In-Memory 저장소인 *레디스가 캐시에 적합하며 상황에 맞는 캐싱 전략을 사용한다면 DB 의 부하를 줄일 수 있고 응답에 대한 지연시간 감소와 처리량 증가로 인해 서비스 성능을 향상시킬 수 있다.
- 레디스(Redis: Remote Dictionary Server)
- Key-Value 구조의 *비정형 데이터를 저장하고 관리하기 위한 오픈 소스 기반의 *비관계형 데이터베이스 관리 시스템
- 모든 데이터를 메모리로 불러와서 처리하는 In-Memory 기반의 DBMS 로, 데이터베이스, 캐시, 메시지 브로커 등으로 사용된다. 주로 캐시 서버를 구현할 때 많이 사용된다.
- 일정 수준 이상 영속성을 지원하는 데이터베이스. 서버가 내려가더라도 디스크나 로그 파일에 저장하여 다시 시작하면 메모리에 로딩할 수 있다.
- 비정형 데이터 : 사전에 정의되거나 형식화되지 않은 데이터, 데이터의 본래 포맷을 그대로 사용할 수 있어서 형식의 자유가 있다. 따라서 정형데이터에 비해 추가적인 가공이 덜 필요하다. 추가적인 전처리가 덜 필요하기 때문에 데이터 축적 속도가 매우 빠른 편이다.
- 비관계형(NoSQL) DB : 테이블 형식 이외의 방법으로 데이터를 저장하고, 비정형 또는 반정형 데이터를 보다 간단하고 유연하며 확장 가능하게 관리할 수 있도록 설계된 데이터베이스로, 키-값, 컬럼 패밀리, 문서, 그래프 등 다양한 형식의 데이터를 처리할 수 있다.
- 레디스(Redis: Remote Dictionary Server)
어떤 정보를 캐시에 담아야 하는가
- 모든 데이터를 캐시에 담기에는 캐시라는 저장 공간은 작다. 그렇기 때문에 파레토의 법칙에 해당하는 소수의 데이터를 선별해야 한다.
- 이때 사용되는 것이 지역성이다.
시간적 지역성
- 특정 데이터가 한 번 접근되었을 경우, 가까운 미래에 또 한 번 데이터에 접근할 가능성이 높은 것을 말한다.
- 메모리 상의 같은 주소에 여러 번 쓰기를 수행할 경우, 상대적으로 작은 크기의 캐시를 사용해도 효율성을 높일 수 있다.
공간적 지역성
- 특정 데이터와 가까운 주소가 순서대로 접근되는 경우를 말한다.
- CPU 캐시나 디스크 캐시의 경우 한 메모리 주소에 접근할 때 그 주소뿐 아니라 해당 블록을 전부 캐시에 가져오게 된다. 이때 메모리 주소를 오름차순이나 내림차순으로 접근한다면, 캐시에 이미 저장된 같은 블록의 데이터를 접근하게 되므로 캐시의 효율성이 크게 향상된다.
- 앞으로 사용할 데이터들이 가져올 블록 안에 모여있는 것을 말한다.
- 필요한 데이터가 모여있다면, 한 번의 메모리 접근으로 필요한 데이터들을 모두 가져올 수 있다.
- 만약 데이터가 모여있지 않다면, Cache Miss 가 발생할 확률이 높아지고, 메모리에 여러 번 접근하게 되어 효율성이 떨어지게 된다.
순차적 지역성
- 데이터가 순차적으로 액세스 되는 경향을 보인다. 프로그램 내의 명령어가 순차적으로 구성된다.
캐싱
- 데이터를 캐시에 저장하는 과정이나 전략
캐시 교체 정책
- 페이지 교체 정책과 개념적으로 유사하다
- FIFO(First In First Out) : 메모리에 가장 먼저 올라온 데이터를 우선적으로 교체하는 알고리즘
- LRU(Least Recently Used) : 가장 오랫동안 사용하지 않은 데이터를 교체하는 알고리즘
- LFU(Least Frequently Used) : 참조 횟수가 가장 낮은 데이터를 교체하는 알고리즘
- NUR(Not Used Recently) : 최근에 사용하지 않은 데이터를 교체하는 클럭 알고리즘
- OPT(Optimal) : 앞으로 가장 오랫동안 사용하지 않을 데이터를 찾아 교체하는 알고리즘
- 자세한 내용
캐시 배치 전략
- 캐시를 이용하게 되면 반드시 닥쳐오는 문제점이 있는데 바로 데이터 *정합성 문제이다.
- 데이터 정합성 : 어느 한 데이터가 캐시(Cache Store)와 데이터베이스(Data Store) 이 두 곳에서 같은 데이터임에도 불구하고 데이터 정보값이 서로 다른 현상
- 적절한 캐시 읽기 전략(Read Cache Strategy)과 캐시 쓰기 전략(Write Cache Strategy)을 통해, 캐시와 DB 간의 데이터 불일치 문제를 극복하면서도 빠른 성능을 잃지 않게 하기 위해 고심히 연구를 할 필요가 있다.
캐시 읽기 전략 (Read Cache Strategy)
1. Look Aside
- 데이터를 찾을 때 우선 캐시에서 데이터를 찾고 데이터가 있다면 캐시에서 데이터를 가지고 오는 전략
- 만약 캐시에 데이터가 없어 Cache Miss 가 발생한다면 앱은 DB 에서 데이터를 가져온 뒤 캐시에 넣어주는 작업을 한다.
- 캐시에 찾는 데이터가 없을 때 DB 에 직접 조회해서 입력되기 때문에 Lazy Loading 이라고도 한다.
- 캐시와 DB 가 분리되어 가용되기 때문에 원하는 데이터만 별도로 구성하여 캐시에 저장할 수 있다.
- 캐시가 다운되더라도 DB 에서 데이터를 가지고 올 수 있다. 하지만, 초기 조회시 Cache Miss 로 인해 무조건 DB 에 접근하기 때문에 DB 에 많은 부하가 생길 수 있다. (Thundering Herd)
- 이런 경우 DB 에서 캐시로 데이터를 미리 넣어주는 작업을 하기도 하는데 이를 Cache Warming 이라고 한다.
- 다만, 캐시 자체는 용량이 작아 무한정으로 데이터를 들고 있을수는 없어 일정시간이 지나면 expire(만료)되는데, 그러면 다시 Thundering Herd 가 발생될 수 있기 때문에 캐시의 *TTL 을 잘 조정할 필요가 있다.
- TTL(Time To Live) : 캐시나 네트워크에서 데이터의 유효 기간을 나타내기 위한 방법
- 단건 호출 빈도가 높은 서비스에 적합하지 않다. 대신 반복적으로 동일 쿼리를 수행하는 서비스에 적합한 아키텍처이다.
2. Read Through
- 캐시에서만 데이터를 읽어오는 전략
- Cache Miss 가 발생하면 캐시는 DB 에서 데이터를 검색하고 캐시에 자체 업데이트한 뒤 앱에 데이터를 보내준다.
- Look Aside 와 비슷하지만 데이터 동기화를 라이브러리 또는 캐시 제공자에게 위임하는 방식이라는 차이가 있다. 그래서 데이터를 조회하는 데 있어 전체적으로 속도가 느리다.
- 데이터 조회를 전적으로 캐시에만 의지하므로, 캐시가 다운될 경우 서비스 이용에 차질이 생길 수 있다. 대신에 캐시와 DB 간의 데이터 동기화가 항상 이루어져 데이터 정합성 문제에서 벗어날 수 있다.
- 역시 읽기가 많은 워크로드에 적합하다.
캐시 쓰기 전략 (Write Cache Strategy)
1. Write Through
- DB 와 캐시에 동시에 데이터를 저장하는 전략으로, 먼저 캐시에 저장한 다음 바로 DB 에 저장하는 방식이다.
- Read Through 와 마찬가지로 DB 동기화 작업을 캐시에게 위임하여 DB 와 캐시는 항상 동기화되어 있다.
- 캐시는 항상 최신 정보를 가지고 있지만, 매 요청마다 두 번의 Write 가 발생하기 때문에 상대적으로 느리고, 빈번한 생성과 수정이 발생하는 서비스에서는 성능 이슈 발생할 수 있다.
- 저장하는 데이터가 재사용되지 않을 수도 있는데 무조건 캐시에 넣어버리기 때문에 리소스 낭비가 발생할 수 있다.
- 이를 방지하기 위해 캐시에 expire time(만료 시간)을 설정하기도 한다.
2. Write Back (a.k.a Write Behind)
- 먼저 캐시에 데이터를 저장했다가 특정 시점마다 DB 에 저장하는 방식
- 캐시에 데이터를 모았다가 한 번에 DB 에 저장하기 때문에 DB 쓰기 비용을 절약할 수 있지만, 데이터를 옮기기 전에 캐시 장애가 발생하면 데이터 유실이 발생할 수 있다.
- 하지만 오히려 반대로 데이터베이스에 장애가 발생하더라도 지속적인 서비스를 제공할 수 있도록 보장하기도 한다.
3. Write Around
- 모든 데이터는 DB 에 저장되고 읽은 데이터만 캐시에 저장되는 방식
- 속도는 빠르지만, Cache Miss 가 발생하는 경우에만 캐시에 데이터를 저장하기 때문에 캐시와 DB 간의 데이터 불일치가 발생하게 된다. 따라서 데이터베이스에 저장된 데이터가 수정, 삭제될 때마다, 캐시 또한 삭제하거나 변경해야 하며, 캐시의 expire 를 짧게 조정하는 식으로 대처해야 한다.
- Write Around 는 주로 Look Aside, Read Through 와 결합해서 사용된다.
'안드로이드 > etc.' 카테고리의 다른 글
[CS] Database 인덱스 (Index) (0) | 2024.09.09 |
---|---|
[CS] JVM 메모리 영역 (Method, Heap, Stack Area) (0) | 2024.08.30 |
[CS] CPU, 주기억장치(ROM, RAM(SRAM, DRAM), 보조기억장치(HDD, SDD) (0) | 2024.08.28 |