캐시란 데이터를 임시로 저장해두는 장소를 말한다. 임시로 저장하여 사용하는 데이터의 종류는 제한이 없기 때문에 작게는 메모리에서 크게는 Logic 혹은 그 이상을 저장할 수 있다.


Cache 의 목적은 로직을 처리하는 데 있어서 빠른 접근성을 제공하는 것이며, 단순히 수동적으로 보관하는 것에 그치지 않고 이를 응용해서 작업의 결과를 저장함으로써 해당 로직의 불필요한 수행을 줄여주는 능동적인 역할까지 수행한다.


캐시가 될 수 있는 것은 일반적으로 로컬 메모리부터 별도의 디스크 볼륨까지 다양하지만 Cache 로 사용하기 위한 가장 중요한 요건은 데이터로의 접근성이다.


Cache 에 대한 접근성은 어떤 경우에도 로직 상에서 원하는 데이터에 직접 접근하거나 만들어내는 비용보다 저렴해야 한다. 그래야만 캐시로서의 의의가 있는 것이다.


그렇기 때문에 Cache 는 접근성이 빠른 공간(Space)에 빠른 자료구조를 사용한다.


캐시서버로 이용되는 서버들은 I/O 에 최적화된 공간이 사용되며 당연히 이에 대한 접근성에 있어서 효율적인 REST 등의 방법을 사용한다. 


컴퓨터 내에서 사용되는 캐시는 RAM보다 빠른 L1,L2 레지스터를 캐시로 사용하고, 프로그램 내에서 구현된 Software Cache 라면 접근에 용이한 Map 과 같은 자료구조에 인메모리(Inmemory)로 저장한다.


다음은 캐시를 이해하는 데 중요한 용어들이다.


 - origin : origin 혹은 origin server 는 캐시에 저장할 실 데이터가 존재하는 공간이다. 웹 캐시라면 DB 서버일 수도 있고, SW 내에서라면 파일 혹은 실행 함수 그 자체일 수도 있다.


 - cache expire : 프로세스 내에서 사용하는 인메모리 캐시나 영구히 상주해야하는 정보를 가진 캐시가 아니라면 Cache 는 Expire Date 를 갖고 있으며 해당 시간이 지나면 상한(Stale) 상태가 된다.


 - cache freshness : 캐시가 만료되지 않은 경우를 fresh 한 캐시라 하고 만료된 경우 stale cache 라 한다.


 - cache hit : 참조하려는 데이터가 캐시에 존재할 때 해당 캐시를 조회하는 걸 Cache hit 이라 한다.


 - cache miss : 참조하려는 데이터가 캐시에 존재 하지 않는 경우


 - cache hit ratio : 적중률로 전체 참조 횟수 대비 Cache hit 된 비율을 의미한다. 실질적으로 캐시의 설계는 Cache hit Ratio 를 높이는 데 초점을 둔다.



다음은 캐시의 동작에 대한 정책들이다.


 Cache Read : 


 - Cache-aside 방식 : 데이터를 참조 하기 전에 참조하고자 하는 값이 캐시에 존재하는지 확인한다. 여기서 값을 직접 비교하기 보다는 키를 이용해서 캐시에 접근한다. 

 Cache에 존재한다면 Cache에서 데이터를 가져온다. 만약 Cache에 존재하지 않는다면 origin에서 데이터를 가져오고 이를 캐시에 저장한다.


 - RT/WT/Write back 방식 : 캐시를 Main Data Source 로 사용하기 때문에 캐시에서만 데이터를 조회한다.

 RT/WT 방식(Read Through / Write Through) 은 Read Scalability 가 가장 뛰어나다.



 Cache Write :


 - Cache-aside 방식 : 캐시를 Application Level 에서 직접 갱신시켜준다. 개발자가 Flow 를 이해하고 Update / Evict 시켜줘야 하며, 그렇지 않으면 Cache 데이터와 DB 데이터가 불일치하는 Stale 현상이 발생한다.


 - Read Through / Write Through 방식 : 데이터의 쓰기시 캐시와 실제 저장공간의 데이터 둘다 최신화 시키는 작업이다. 

 캐시를 메인 Database 로 사용하는게 특징적이며, 캐시에 데이터를 먼저 업데이트하고 캐시에서 Main Database 를 즉시 갱신시킨다.

 양쪽의 데이터를 동일하게 유지할 수 있지만, 쓰기 시에 추가 부하가 생긴다는 단점이 있다.


 - Write Back 방식 : 데이터의 쓰기시 캐시의 데이터만 최신화 하고 해당 Cache 를 Evict 시켜놓는다. 이 후 RT/WT 방식처럼 캐시 값을 마킹된 기준으로 origin 으로 직접 반영(Write) 하는데, 캐시가 별도의 큐를 이용해서 Database Source를 비동기로 Update 시켜준다.

 Write Performance 와 DB Scalability 에 있어서 가장 뛰어나다.

 쓰기 작업이 Cache 에서만 발생하지만, Cache 가 만료되는 시점까지 Origin 에 Write Failure 가 발생한다면 데이터를 영구 손실할 위험이 존재한다. 



 Cache Replacement


  웹 캐시의 경우 자동 expire 하거나 명시적으로 cache 를 지워주는 동작을 해주지만, 캐시를 Scheduling 에 사용하는 컴퓨터나 알고리즘의 경우 Replicement Policy 를 갖는다.



 다음은 몇가지 대표적인 알고리즘들이다.


  - FIFO(First In First Out) : 오래된 캐시를 먼저 비우고 새로운 캐시를 추가하는 방식이다.


  - LIFO(Last In First Out) : 가장 최근에 반영된 캐시가 먼저 지워진다.


  - LRU(Least Recently Used) : 가장 최근에 사용되지 않는 순서대로 캐시를 교체한다. 가장 오랫동안 사용되지 않은 캐시가 삭제되며 일반적으로 사용되는 방식이다.


  - MRU(Most Recently Used) : 가장 최근에 많이 사용되는 순서대로 캐시를 교체한다. 휘발성 메모리를 이용해야 하는 특수한 상황에 사용된다.


  - Random : 말그대로 랜덤으로 캐시를 교체한다.


 운영체제를 배웠다면 페이지 교체 알고리즘이 Cache Replacement 정책을 사용한다는 것을 알 수 있을 것이다.



본 포스팅에서는 넓은 범위의 Cache 의 정의와 목적, 정책들에 대해 정리해보았다.


이론적인 부분이고 웹 캐시와는 조금 다르기도 하지만 중요한 기본 개념은 잘 숙지해두자.


참조 : 

https://en.wikipedia.org/wiki/Cache_replacement_policies

https://codeahoy.com/2017/08/11/caching-strategies-and-how-to-choose-the-right-one/

https://gomguard.tistory.com/115

https://onecellboy.tistory.com/260

https://dzone.com/articles/using-read-through-amp-write-through-in-distribute

+ Recent posts