레디스를 캐시로 잘 활용하기 위해서는 어떤 캐싱 전략을 적절히 도입하느냐에 따라 다르다.
이 적절히라는 말은 캐싱 전략을 데이터의 특성과 엑세스 패턴을 잘 고려해 적용하냐는 것이다.
어떤 캐싱 전략들이 있는지 한 번 알아보고 자신의 목적에 맞는 캐싱 전략을 선택할 수 있도록 하자.
Redis에 대해 알아보고 싶다면 아래 포스팅을 참고하자.
2023.09.11 - [◼ CS 기초 지식/[데이터베이스]] - [Redis] 레디스란? 특징, 활용예시, 비교 정리
읽기 전략
Look Aside 전략
1. cache에서 원하는 cache 데이터가 있는지 조회 (Cache Hit)
2. 없다면 DB에서 조회 (Cache Miss)
3. DB에서 조회한 데이터를 cache에 업데이트
데이터를 반복적으로 읽는 작업이 많을 때 사용하는 가장 일반적인 전략이다.
이 전략은 cache에 장애가 발생하더라도 Server에 영향을 주지 않고 DB에서 데이터를 가져올 수 있다.
하지만 'Cache Miss' 상황에서 cache로의 커넥션이 많다면 이 많은 커넥션이 DB로 몰릴 수 있다.
예를 들어, cache를 새로 도입했거나 재시작 후에는 캐시가 비어있는 상태이기 때문에
이때 갑자기 많은 요청이 들어오면 ‘Cache Miss’로 모든 요청이 DB로 직행한다.
이 때 DB에 급격한 부하가 발생할 수 있고, 응답 시간도 느려질 수 있다.
이 문제를 방지하기 위해 DB에 저장된 데이터를 cache에 미리 추가해주는 cache warming 작업이 필요하다.
Read Through 전략
1. cache에서 원하는 cache 데이터가 있는지 조회 (Cache Hit)
2. 없다면 cache가 DB에서 데이터를 직접 로드해 저장 (Cache Miss)
3. cache에서 데이터 조회
캐시에서만 데이터를 읽어오는 전략이다.
'Cache Miss' 발생 시 두 번의 네트워크를 타기 때문에 Look Aside에 비해 상대적으로 느리다.
또한 cache에서 모든 데이터 접근을 중앙화하고 있기 때문에 장애 발생시 전체 장애로 이어진다.
이 전략을 사용하기 위해서는 cache 데이터를 분산 하는 작업(Replication, Cluster)으로 고가용성을 보장할 필요가 있다.
쓰기 전략
Write Back 전략
1. 모든 데이터를 cache에 저장한다.
2. cache에서 일정 시간 마다 배치 처리로 DB에 저장한다.
cache에서 일정 시간 마다 배치 처리로 DB에 저장하기 때문에 쓰기 작업이 많은 경우 유용하게 사용할 수 있다.
(ex: 쓰기 작업이 빈번한 로그를 DB에 저장하는 경우 이 전략을 많이 쓴다고 함.)
하지만 In-Memory(인 메모리)이기 때문에 재시작 또는 장애 발생 시 데이터 유실 위험이 있다는 점을 주의해야한다.
RDB, AOF 또는 데이터 분산으로 이 유실 문제를 해결 할 순 있겠지만
현재 구조가 이 방법을 선택하기 적절할지에 대해서는 트레이드 오프를 잘 고려해 선택해야할 것이다.
Write Through 전략
1. cache에 데이터 저장
2. DB에 데이터 저장
항상 데이터를 저장할 때 cache와 DB 둘 다 저장한다.
cache는 항상 최신의 정보를 갖는다는 장점을 갖지만, 저장할 때마다 2번의 통신이 이뤄져야하므로 상대적으로 느리다.
또한 무조건 cache에 데이터를 저장한다는 점에서 재사용되지 않을 데이터가 들어갈 수 있어 리소스 낭비로 이루어 질 수 있다.
이 문제를 해결하기 위해 일정 시간 동안만 데이터를 보관한다는 TTL을 설정이 꼭 필요하다.
Write Around 전략
일단 모든 데이터를 DB에만 저장하고, 'Cache Miss'가 발생한 경우에만 cache에서 데이터를 가져온다.
이 시점에서 DB의 데이터와 cache의 데이터가 일치하지 않은 정합성 문제가 발생할 수가 있다.
이 문제를 해결하기 위해 데이터 변경이 일어날 때마다 cache를 삭제하거나 변경해줘야한다.
'Cache Miss' 발생 시 cache에서 데이터를 읽는다 했는데 cache에 저장 자체를 안하고 있어 어떻게 읽냐할 수 있다.
캐싱 전략은 읽기, 쓰기 전략 두 가지를 사용하므로 선택한 읽기 전략에 따라 cache에서 데이터를 읽어 온다.
주의할 점
너무 짧거나, 너무 긴 TTL = OTL
TTL이 설정되어 있지 않다면 클라이언트는 오래된 캐시 데이터를 받아 볼 수 있는 문제점이 있다.
또한 In-Memory라는 특성으로 디스크 보다 용량이 훨씬 적기 때문에 이 메모리 관리도 민감한 부분이다.
따라서 cache를 저장할 때 기본적으로 TTL을 설정하는 것이 중요하다.
만약 TTL이 너무 짧다면 어떨까?
대규모 트래픽을 받는 서비스이고 서버들이 나눠져있다면 TTL이 짧을 경우 'Cache Stampede' 현상이 발생할 수 있다.
'Cache Stampede'란 cache가 만료되어 다수의 서버들이 동시에 같은 데이터를 DB에서 조회하는 duplicate read가 발생하고
읽어온 값을 동시에 cache에 저장하는 duplicate write가 발생한다.
이는 불필요한 작업들이 늘어나 응답 시간 증가와 장애까지로 이어질 수 있다.
띠라서 TTL을 너무 짧게 설정하는 것을 주의해야한다.
반대로 너무 길다면 어떨까?
만약 주간 랭킹 시스템을 도입했고, TTL을 30일로 설정했다고 하면 1주일 마다 갱신되어야할 데이터가 30일동안 유지되어
적절하지 않은 랭킹을 보여줌과 동시에 너무 많은 데이터를 쌓아두는 상황이 발생할 수 있다.
메모리 관리는 민감한 부분임으로 너무 길게 설정하는 것도 주의할 필요가 있다.
따라서, 비즈니스 요구사항에 맞춰 너무 짧지거나 길지 않은 적절한 TTL을 설정하는 것이 필요하다.
캐시 공유 시 정합성 문제
여러 서버가 하나의 cache를 공유해 사용할 경우 A 서버가 추가한 캐시를 B 서버가 변경해버릴 수 있다.
이 정합성 문제를 방지하기 위해서 분산 락, Spring CacheManager의 sync 옵션 등을 고려하여
각각의 서버마다 데이터의 충돌을 방지할 수 있도록 설계할 필요가 있다.
출처
'◼ CS 기초 지식 > [데이터베이스]' 카테고리의 다른 글
[MySQL 8.0] 서버 설정, 시스템 변수 정복하기 (2) | 2024.11.12 |
---|---|
[DB] 파티셔닝과 샤딩? 쉽게 알아가보자 (1) | 2024.11.11 |
[MySQL] DB 레플리케이션에 대해 알아보자. (8) | 2024.11.09 |
[데이터베이스/JPA] 낙관적 락, 비관적 락이란? 예시를 통해 쉽게 알아보자 (5) | 2024.08.27 |
B-Tree란? 구조와 연산 과정을 살펴보자 (1) | 2024.08.26 |