[TIL] Redis와 Cache

Soo·2023년 11월 20일
post-thumbnail

이전 실시간 채팅 클론코딩 프로젝트를 진행했을 때, Redis를 사용했었는데 회사에서도 Redis를 사용하고 있어 이에 대해 다시 다져보기로 한다.

❓ Redis란

Redis(Remote Dictionary Server)의 줄임말로, dictionary 구조 한마디로 key-value 형태로 데이터를 저장하고 관리하는 서버를 의미한다.

아래에는 공식 홈페이지(https://redis.io/)와 같이 Redis의 핵심기능에 대해 정리해보았다.

Redis는 데이터베이스, 캐시, 메세지 브로커 및 스트리밍 엔진으로 사용되는 오픈소스(BSD 라이선스), 인메모리 데이터 구조 저장소이다.

Redis는 strings, hashs, lists, sets, sorted sets, streams와 같은 컬렉션을 제공한다.

Redis에는 복제, Lua 스크립팅, LRU 추출, 트랜잭션 및 다양한 수준의 디스크 지속성이 내장되어 있으며 고가용성을 제공한다.

Redis Sentinel 및 Redis 클러스토를 통한 자동 파티셔닝을 제공한다.

Redis의 특징 및 장단점

1. 성능
모든 Redis 데이터는 메모리에 저장되어 대기 시간을 낮추고 처리량을 높인다.
평균적으로 읽기 및 쓰기의 작업속도가 1ms로 디스크 기반 데이터베이스보다 빠르다.

2. 유연한 데이터 구조
앞서 말했듯이 Redis의 데이터는 String, List, Set, Hash, Sorted Set, Bitmap, JSON 등 다양한 데이터 타입을 지원한다. 따라서, 애플리케이션의 요구 사항에 알맞는 다양한 데이터 타입을 활용할 수 있다.

3. 개발 용이성
Redis는 쿼리문이 따로 필요로 하지 않고, 단순한 명령 구조로 데이터의 저장 및 조회 등이 가능하다.

4. 영속성
Redis는 영속성을 보장하기 위해 데이터를 디스크에 저장할 수 있다. 서버에 치명적인 문제가 발생하더라도 디스크에 저장된 데이터를 통해 복구가 가능하다.

5. 싱글스레드 방식
Redis는 싱글 스레드 방식을 사용하여 한 번에 하나의 명령어만을 처리한다. 따라서 연산을 원자적으로 처리해 Race Condition이 거의 발생하지 않는다.
다만, 멀티 스레드를 지원하지 않기 때문에 시간 복잡도가 O(n)인 명령어의 사용은 주의해서 사용해야한다.

❗️ Redis의 사용 사례

  • 캐싱
  • 채팅, 메시징 및 대기열
  • 랭킹 보드(순위표)
  • 인증 토큰 저장(세션 스토어)
  • 다양한 미디어 스트리밍
  • 실시간 분석
  • 위치기반 데이터 타입 사용

그렇다면 캐시는 무엇일까?

캐시(Cache)

Cache는 '자주 사용하는 데이터나 값을 미리 복사해놓는 임시장소'를 의미한다. 캐시는 저장공간이 작고 비용이 비싼 대신 빠른 성능을 제공한다.

캐시의 등장

캐시란 나중에 요청할 결과를 미리 저장해둔 후 빠르게 서비스해주는 것을 의미한다. 즉, 미리 결과를 저장하고 나중에 올 요청에 대해 DB 또는 API를 참조하지 않고 캐시에 접근해 오청을 처리하게 된다. 이러한 캐시가 동작할 수 있는 철학에는 파레토법칙이 있다.

💡 파레토 법칙이란
80%의 결과는 20%의 원인으로 인해 발생한다는 것을 의미한다.

즉, 이것은 바로 캐시가 효율적일 수 있는 이유이다. 모든 결과를 캐싱할 필요는 없고, 그 말은 곧 우리는 서비스를 할 때 많이 사용되는 20%를 캐싱한다면 전체적으로 영향을 주어 효율을 극대화할 수 있다는 뜻이다.

그렇다면 어떤 정보를 캐시에 담을까?

모든 데이터를 캐시에 담기에는 캐시는 저장공간이 작다. 그렇기 때문에 파레토의 법칙에 해당하는 소수의 데이터를 선별해야만 한다. 이 때 사용 되는 것이 바로 지역성(Locality)이다.

💡 캐시의 지역성(Cache Locality)이란
캐시 메모리의 역할을 제대로 수행하기 위해서는 CPU가 어떤 데이터를 원할 것인가를 어느정도 예측할 수 있어야 한다. 캐시의 성능은 작은 용량의 캐시 메모리에 CPU가 이후에 참조할, 쓸모있는 저보가 어느 정도 들어있느냐에 따라 좌우되기 때문이다.

이 때 적중률을 극대화시키기 위해 데이터 지역성(locality)를 사용한다. 지역성의 전제조건으로 프로그램은 모든 코드나 데이터를 균등하게 Access하지 않는다는 특성을 기본으로 한다. 즉, Locality란 기억 장치 내의 정보를 균일하게 Access하는 것이 아닌 어느 한 순간에 특정부분을 집중적으로 참조하는 특성이다.

🗂️ 지역성의 종류

  1. 시간적 지역성(Temporal Locality)
    특정 데이터가 한 번 접근 되었을 경우, 최근에 참조된 주소의 내용은 곧 다음에 다시 참조되는 것을 의미한다. 메모리 상의 같은 주소에 여러차례 쓰기를 수행할 경우, 상대적으로 작은 크기의 캐시를 사용해도 효율성을 꾀할 수 있다.

  2. 공간적 지역성(Spatial Locality)
    기억장치 내에 서로 인접하여 저장되어 있는 데이터들이 연속적으로 엑세스될 가능성이 높아지는 특성을 가지고 있다.

⛓️ 캐시의 사용 구조

  1. Client로부터 요청을 받는다
  2. Cache와 작업을 한다.
  3. 실제 DB와 작업을 한다.
  4. 다시 Cache와 작업한다.

Cache는 일반적으로 위와 같은 flow로 사용된다. 동일한 flow에서 어떻게 사용하냐에 따라서 look aside cache(Lazy Loading)와 write back으로 나뉜다.

❗️ look aside cache(Lazy Loading)

  1. Web server는 데이터의 존재 유무 확인을 위해 cache를 확인
  2. Data가 존재한다면 cache에서 데이터 가져옴
  3. Data가 존재하지 않다면, cache의 실제 DB Data 사용
  4. DB에서 읽어온 Data를 Cache에 다시 저장
  • look aside cache는 캐시를 한 번 접근해 데이터 존재유무를 판단한 후, 있다면 캐시의 데이터를 사용/없다면 실제 DB 또는 API 호출하는 로직으로 구현된다.
  • 대부분의 캐시를 사용한 개발이 해당 프로세스를 따르고 있다.

❗️ write back

  1. Data를 Cache에 저장
  2. Cache에 있는 Data를 일정 기간동안 체크
  3. 모여있는 Data를 DB에 저장
  4. Cache에 있는 Data 삭제
  • write back은 캐시를 다르게 이용하는 방법이다. DB는 접근 횟수가 적을수록 전체 시스템의 퍼포먼스는 좋아진다. 데이터를 쓰거나 많은 데이터를 읽게 되면 DB에서 Disk를 접근하게 된다.
  • 이렇게 되면 Application의 속도 저하가 일어날 수 있다. 따라서 write back은 데이터를 캐시에 모으고 일정한 주기 또는 일정한 크기가 되면 한 번에 처리한다.
profile
Soogineer's Devlog

0개의 댓글