[Nest&Redis] Cache-Aside Pattern

sjy0917·2022년 6월 24일
2

Nest

목록 보기
11/13
post-thumbnail

왜썻나

기업협업을 진행하면서 프로젝트에 다양한 검색이 생기면서 여러요청이오면 디비에 과부하가 올거같아 부트캠프 진행중에 써봤던 In-Memory DB중 하나인 Redis가 생각나 적용시켜보기로 했다

어떻게 썻니

캐시란?

데이터나 값을 저장하는 임시저장소

  • 원본 데이터 접근보다 빠름
  • 같은 데이터를 반복적으로 접근하는 상황에 사용하기 알맞음
  • 잘 변하지 않는 데이터일수록 효과적

추상적인 웹 서비스 구조

  1. 클라이언트가 웹서버에 접속한다
  2. 웹 서버가 DB에 데이터를 읽거나 쓰기를 요청
  3. DB에서 웹서버로 전송
  4. 웹서버가 클라이언트로 전송

이 과정중 DB의 내부 캐시용량이 Memory보다 크다면 Disk를 써야하는데 속도가 굉장히 느려질 수도 있다

Cache-Aside

Cache-Aside는 Redis를 캐시로 사용할때 보편적으로 사용하는 방법인데,
그 과정은
1. App이 데이터를 찾을때 먼저 캐시를 찾는다
2. 캐시에 데이터가 있다면 데이터를 읽는다
3. 만약 2에서 없다면 DB에 접근해서 데이터를 가져온뒤 캐시에 저장하는 과정을 거친다

코드

검색기능이 있는 API에서 사용하는 공통 Redis

import { CACHE_MANAGER, Inject, Injectable } from '@nestjs/common';
import { Cache } from 'cache-manager';

@Injectable()
export class RedisService {
  constructor(
    // Redis
    @Inject(CACHE_MANAGER)
    private readonly cacheManager: Cache,
  ) {}

  async findRedis(condition: string) {
    const redisRes = await this.cacheManager.get(condition);
    return redisRes;
  }

  async setRedis(condition, result) {
    await this.cacheManager.set(condition, result, {
      ttl: 2,
    });
  }
}

사용하는곳의 코드

@Injectable()
export class CourseService {
  constructor(
    @InjectRepository(Course)
    private readonly courseRepository: Repository<Course>, //
    private readonly categoryService: CategoryService, //
    private readonly discountCourseService: DiscountCourseService,

    @InjectRepository(UserCourse)
    private readonly userCourseRepository: Repository<UserCourse>, //

    private readonly connection: Connection,
    private readonly redisService: RedisService,
  ) {}

위처럼 주입받은 후

    const searchCondition = `${tagName}${status}${searchInputType}${inputString}${take}${page}`;

    const redisRes = await this.redisService.findRedis(searchCondition);
    if (redisRes) {
      return redisRes;
    }

검색한 결과가 있다면 Return 시키고 없다면

    await this.redisService.setRedis(searchCondition, searchResult);

    return searchResult;

Redis에 Set을 시킨후 DB에 긁어온 데이터를 Return 시킨다.

TTL을 초기에는 10초정도로 길게 설정했는데 프론트엔드분들이 아우성을 치고 실제로 나도 불편함이 많아져 2초정도로 줄였다.

이런 구조를 사용한다면 Redis가 다운되더라도 바로 장애가 나오는게 아니라 DB에서 데이터를 긁어올수있다.

하지만 단점으로는 그 2초동안의 정보가 갱신이 되지않아 항상 최신 정보가 나오지 않는다는거다 이점은 Cache를 쓰면 생기게되는 Trade Off라고 생각함..

참고한곳


캐시어사이드 패턴 in 레디스

0개의 댓글