캐시(Cache)
데이터나 값을 미리 복사해 놓는 임시 장소를 가리킨다.
캐시는 캐시의 접근 시간에 비해 원래 데이터를 접근하는 시간이 오래 걸리는 경우나 값을 다시 계산하는 시간을 절약하고 싶은 경우에 사용한다.
메모리
컴퓨터 메모리(데이터를 저장하는 공간)의 속도와 용량은 반비례 관계
- 속도가 빠른 메모리일수록 용량이 작음
- 용량이 큰 저장장치는 속다가 느림
- 데이터 저장 공간은 속도와 용량에 따라 특성에 맞게 역할을 나누어서 사용
메모리를 속도-용량 순서대로 쌓으면 피라미드와 같은 형상이 나타난다.
메모리 계층 구조(Memory hierarchy)
데이터 지역성의 원리
파레토의 법칙 = 2대 8의 법칙
자주 쓰이는 데이터는 시간적 혹은 공간적으로 한 곳에 몰려 있을 가능성이 높다.
- 시간 지역성 (Temporal Localiry)
- 공간 지역성 (Spatial Locality)
- 순차 지역성
캐시 작동 방식
- 원본 데이터(System-of-Record)와는 별개로 자주 쓰이는 데이터(Hot Data)들을 복사해둘 캐시 공간을 마련한다. 캐시 공간은 상수 시간 등 낮은 시간 복잡도로 접근 가능한 곳 즉, 접근 시간이 원본 데이터에 접근하는 속도보다 훨씬 빠르게 접근 가능한 곳을 주로 사용한다.
- 데이터를 달라는 요청이 들어오면, 원본 데이터가 담긴 곳에 접근하기 전에 먼저 캐시 내부부터 찾는다.
- 캐시에 원하는 데이터가 없거나(Cache), 너무 오래되어 최신성을 잃었으면(Expiration) 그때서야 원본 데이터가 있는 곳에 접근하여 데이터를 가져온다. 이때 데이터를 가져오면서 캐시에도 해당 데이터를 복사하거나 혹은 갱신한다.
- 캐시에 원하는 데이터가 있으면 원본 데이터가 있는 공간에 접근하지 않고 캐시에서 바로 해당 데이터를 제공한다. (Cache hit)
- 캐시 공간은 작으므로, 공간이 모자라게 되면 안 쓰는 데이터부터 삭제하여 공간을 확보한다. (Eviction)
여러 캐시들
CPU의 캐시 메모리
- 아무리 빠른 주기억장치도 CPU를 따라가기 어려워 SRAM이라는 특수한 메모리를 CPU에 넣어 캐시 메모리로 사용한다.
하드디스크
- CPU에 비해 10만 배 이상 느린 장치
- 처리 효율을 올리기 위해 자주 쓰이는 데이터를 캐싱해주는 캐시가 들어감
데이터베이스
- 하드디스크나 SSD 위에서 돌아가므로 쿼리를 실행하여 데이터를 읽고 쓰는 것은 시간이 오래 걸리는 작업이다.
- 데이터베이스는 쓰기보다 읽기가 많으므로, 자주 요청받는 쿼리의 결과를 캐싱해두면 효율이 오른다.
- 데이터베이스 자체에서 별도의 캐시를 운영한다. (JPA의 영속성 컨텍스트도 캐시의 일종이다.)
CDN
- 국제 인터넷 회신은 비싸고 용량을 늘리기 어렵다.
- 구글은 각 통신사마다 Google Global Cache를 두어 인기 있는 동영상은 미국 서버까지 접속할 필요 없이 국내 서버에서 처리하도록 한다.
- 세계 각지에 캐시 서버를 두어 전송속도를 높이고 부하를 분산하는 시스템이 CDN이다.
웹 캐시
- 네트워크를 통해 데이터를 가져오는 것은 하드디스크보다 느릴 때가 많다.
- 웹 브라우저는 웹 페이지에 접속할 때, 자원을 하드디스크나 메모리에 캐싱해 뒀다가 다음 번에 다시 접속할 때 이를 재활용한다. → 브라우저 캐시
- 웹 서버 또한 동적 웹 페이지라 할지라도 매번 내용이 바뀌지 않는 경우가 더 많으므로, 서버에서 생성한 HTML을 캐싱해 뒀다가 다음 번 요청에 이를 재활용한다. → 응답 캐시
- 이와 유사하게, 클라이언트에서 자주 요청받는 내용은 웹 서버로 전달하지 않고 웹 서버 앞단의 프록시 서버에서 캐싱해둔 데이터를 바로 제공하기도 한다. → 프록시 캐시
브라우저 캐시
- 웹 서버에서 클라이언트에 보내는 HTTP헤더에 캐시 지시자를 삽입하면, 웹 브라우저는 해당 지시자에 명시된 캐시 정책에 따라 캐싱을 실시한다.
- 캐시의 유효 시간이 지나도 캐시된 데이터가 바뀌지 않은 경우를 확인하기 위해 ETag라는 유효성 검사 토큰을 사용한다. 캐싱 된것을 무효화하고 다시 받아올 필요가 있는지 판단한다.
캐싱 기간을 길게 잡았는데 그 사이에 웹페이지를 수정하면서 이전에 캐싱된 파일로 웹브라우저 상에선 옛날 버전의 파일들이 계속 나오는 경우가 발생할 수 있다. 이런 경우에는 예를 들어 CSS의 버전이 바뀌었을 때 버전 번호를 파일 이름 뒤에 붙인다. HTTP헤더에 붙이면 파일 이름이 달라지면 무효화가 된다. 파일 이름의 뒤에 버전 번호나 이름을 붙여 캐시 유효기간을 길게 집으면서도 변경사항이 생겼을 때 업데이트를 신속하게 적용한다.
- 캐시 유효 시간을 최대한 길게 잡으면서도 static 파일의 업데이트를 신속히 적용하기 위해 정적 파일의 이름 뒤에 별도의 토큰이나 버전 번호를 붙인다.
- 캐시 정책은 해당 웹 페이지의 전반적인 상황에 따라 각 파일마다 다르게 적용되어야 한다. 적어도 정적 파일과 동적인 부분의 브라우저 캐싱 정책은 달라야한다. 비공개 정보가 담긴 페이지는 보안상 아예 캐싱을 막아야 할 수도 있다.
Redis(Remote Dictionary Server)
여기서 Dictionary는 Java 기준 HashMap, HashTable을 일컫는다.
- 메모리 기반 오픈소스 NoSQL DBMS의 일종으로, 웹 서비스에서 캐싱을 위해 많이 쓴다.
- 모든 데이터를 메모리에 다 올려서 처리하여 속도가 빠르다.
- 서버 재부팅 때 메모리의 데이터가 휘발되지 않게끔 데이터를 하드디스크에 기록할 수 있다.
- DBMS의 일종으로, 명시적으로 삭제하지 않는 한 메모리에서 데이터를 삭제하지 않는다.
- 자체적으로 여러 가지 자료형을 지원한다.
EHcache
- Java의 표준 캐싱 API명세서인 JSR-107을 따르는 오픈소스 캐시 구현체
- Spring 프레임워크나 Hibernate ORM 등에서 바로 사용 가능하다.
- Java 진영에서 가장 널리 쓰인다고 한다.
- 캐시 저장공간을 속도에 따라 여러 등급(Tier)으로 나누어 메모리 계층 구조를 적용 가능하다.(3단계)
- 메모리에 캐시된 내용을 하드디스크에 기록 가능하다.
- 대규모 서비스에서 캐시 서버 여럿을 클러스터로 묶을 수 있는 기능 제공한다.
캐싱 Caching
Caching == Cache + ing
Cache : 자주 필요한 데이터나 값의 복사본을 일시적으로 저장, 보관하기 위해 사용하는 곳
Cacheing : cache를 사용하는 것
병목 현상을 완화하기 위해 CPU와 메인 메모리(RAM) 사이에 크기는 작지만 속도가 빠른 캐시 메모리를 두고, 향후 재사용할 가능성이 클 것으로 예상되는 데이터의 복사본을 저장해 둔 CPU가 요청하는 데이터를 바로바로 전달할 수 있도록 한다.
DRAM(메인 메모리) : 트랜지스터가 1개이고, 비용이 SRAM에 비해 저렴하다.
SRAM(캐시 메모리) : 차지하는 면적도 크고 트랜지스터가 6개로 구조가 복잡하고, 비용도 비싸다.
캐시 메모리를 포함한 메모리 계층 구조
↑ 빠름, 비쌈, 작은 용량, CPU와 가까움 |
CPU Register |
Cache Memory | |
Main Memory(RAM) | |
Secondary Memory |
한 계층은 바로 아래 계층에 대하여 캐싱 작업을 수행한다. 레지스터가 캐시 메모리를 캐싱하고, 캐시 메모리가 램을 캐싱하고, 캐시 메모리가 램을 캐싱하고 메인 메모리도 하드 디스크를 캐싱한다.
메모리 계층 구조의 목적은 캐싱을이용하여 빠르고 작은 메모리와 크고 느린 메모리의 장점을 조합해서 크고 빠른 메모리처럼 행동하도록 만드는 것이다.
재사용성할 가능성이 클지는 어떻게 알 수 있을까?
데이터 지역성의 원리를 이용한다.
데이터 지역성의 원리란 데이터 접근이 시간적 혹은 공간적으로 가깝게 일어나는 것을 의미한다.
CPU가 메모리에 데이터를 요청할 때, 메인 메모리에 접근하기 앞서 캐시 메모리에 접근하여 데엍 존재 여부를 확인한다. 캐시 메모리가 해당 데이터를 가지고 있으면 Cache Hit, 해당 데이터가 없어 메인 메모리에서 가져와야하면 Cache Miss라고 한다.
미스가 발생하면 캐싱을 하는데 Hit 상태에서 데이터 쓰기 동작이 발생한다면 두 가지 정책이 있다.
CPU에서 데이터를 읽는 동작이 아니라 입력하는 동작이 발생하고 데이터를 변경할 주소가 캐싱된 상태라면 메모리의 데이터가 업데이트되는 대신 캐시의 데이터가 업데이트 된다. 따라서 메인 메모리를 업데이트 해주어야 한다.
메인 메모리를 업데이트하는 시점에 따라 정책이 두 가지로 나뉜다.
- Write Through 정책 : 메인 메모리를 바로 업데이트 해주는 것이다. 단순하고 캐시와 메인 메모리의 일관성을 유지할 수 있지만 매번 업데이트해 줘야하므로 시간이 걸린다는 단점이 있다.
- Write Back 정책 : 캐시만 업데이트하다가 업데이트 된 데이터가 캐시에서 빠지게 될 때 메인 메모리를 업데이트해주는 정책이다. 속도가 빠르지만 캐시와 메모리가 서로 값이 다른 경우가 발생할 수 있다. 데이터가 변경됐는지 확인하기 위해 캐시 블록마다 dirty 비트를 추가해야하며, 데이터가 변경되었다면 1로 변경한다. 이후 해당 블록이 교체될 때 dirty 비트가 1이라면 메모리의 데이터를 변경하는 방식이다. 캐시 일관성을 지키기위한 기법도 존재한다.
캐싱은 캐시의 데이터나 계산된 결과 값의 복사본을 저장해 둠으로써 전체적인 처리 속도를 향상시킨다.
- 데이터에 직접적으로 접근하는데 걸리는 시간이 오래 걸릴 때
- 필요한 값을 얻기 위해 계산하는 과정을 생략하고 싶을 때
- 반복적으로 동일한 결과를 돌려주는 경우
캐싱은 복사본과 원본의 일관성 유지에 유의해야한다.
참고 영상
- 캐시
'Web' 카테고리의 다른 글
JWT, Json Web Token에 대해 알아보기 (0) | 2022.05.01 |
---|