Search

Cache 도입 건 - AWS Redis, Memcached, ValKey

생성일
2025/01/15 07:55
태그
AI 요약
날짜
상위 항목
하위 항목

개요

캐시란 데이터를 메모리에 저장하여 빠르게 접근할 수 있는 고속 저장소이다.
자주 사용되는 데이터를 캐시에 저장하면 데이터베이스를 호출하지 않고 데이터를 빠르게 반환해줄 수 있어 조회 속도가 매우 빠르며, 데이터베이스가 크게 줄어들게 되고 서비스 성능이 향상된다.
타이어픽 서비스는 고가용성을 위해 Scale-Out하여 동일한 서버를 2대 이상 운영하고 있다.
하지만 로컬 캐시만을 사용하게 된다면 데이터 정합성 문제로 인해 서비스 운영에 문제가 발생할 여지가 있다.
이런 문제로 인해 글로벌 캐시를 사용하게 되며, 서버 내에 캐시를 저장하지 않고 모든 서버가 글로벌 캐시를 바라보게 되며 데이터 정합성 문제를 해결 할 수 있게 된다.
그렇다면 무조건 로컬 캐시가 아닌 글로벌 캐시가 유리하다라고 할 수 있는가? 라고 했을 때 다음과 같은 장점을 가지기 때문에 그렇다고도 할 수 없다.
1.
빠른 응답속도 - 글로벌 캐시도 결국 별도의 서버이기 때문에 네트워크 트래픽을 사용하게 된다.
2.
의존도가 감소한다.
그리고 어떤 저자는 이렇게 얘기하기도 한다. 굳이 글로벌 캐시를 사용하지 않아도 Eventual Consistency(최종적 일관성)으로 인해 일시적으론 불일치하지만 결과적으로 서버의 데이터는 동일하게 맞춰진다는 것
다만 Scale-In-Out 되는 분산처리 시스템 상 서버 상의 로컬 캐시가 분실될 수 있으며 배포로 인해 Task가 재배치된다면 Rolling에 의해 로컬 캐시는 분실된다.
잦은 배포와 기획전, 이벤트 등을 진행하는 타이어픽 서비스 특성상 로컬 캐시와 글로벌 캐시를 혼합하여 사용하기보다는 글로벌 캐시를 채택하게 되었다.

어떤 글로벌 캐시를 사용할까?

대부분의 인프라가 AWS에 의존중이므로 AWS 내에서 제공하는 ElastiCache를 사용하기로 결정했다. AWS ElastiCache는 ValKey, Memcached, Redis OSS를 선택하여 사용 할 수 있다. ValKey, Redis의 경우 다양한 데이터 구조를 제공하고, 트랜잭션, Pub/Sub messaging, Lua Script 지원등 여러 기능에 대한 제공과 확장성에 초점을 두고 있고 Memcache의 경우 멀티쓰레드를 지원하여 더욱 많은 작업을 처리할 수 있다는 장점이 있다. 현재 타이어픽 서비스에서 캐싱은 주로 자주 사용되는 데이터 중 SlowQuery가 발생하는 건에 대해서 저장하는 용도로 사용 중이므로 스트리밍이나 채팅과 같은 실시간 처리속도가 중점이 아니기 때문에 확장성을 염두해둔 ValKey와 Reids가 맞다는 판단이 든다. ValKey의 경우도 Redis와 동일한 기능을 제공한다고하지만 NestJS 프레임워크와의 레퍼런스를 보았을 때 전체적으로 Redis를 채택하였다.

npm install

nestjs에서 redis와 연동하기 위해 아래 라이브러리를 먼저 설치 (현재 nestjs와 맞는 버전을 사용한다)
npm install @liaoliaots/nestjs-redis@10.0.0 ioredis@5.4.2
YAML
복사

redis-cache.module.ts

모든 Module에서 cache 사용을 위해 @Global 데코레이터를 추가해준다.
REDIS 환경변수 값을 포함하고 있기 때문에 forRoot로 선언한 뒤 Option값을 주입한다.
@Global() export class RedisCacheModule { static forRoot(options?: RedisCacheModuleOptions): DynamicModule { return { controllers: [RedisCacheController], module: RedisCacheModule, providers: [ RedisCacheService, { provide: constants.default.etc.CONFIG_OPTIONS, useValue: options }, ], exports: [RedisCacheService], }; } }
TypeScript
복사

app.module.ts

RedisModule.forRoot({ closeClient: true, readyLog: true, errorLog: process.env.NODE_ENV === 'develop' ? true : false, config: { host: process.env.REDIS_HOST, port: Number(process.env.REDIS_PORT), retryStrategy: (times) => { const maxRetries = 10; if (times > maxRetries) return; // 지수백오프 재시도 딜레이 설정 const delay = Math.min(times * 50, 2000); return delay; }, }, }), RedisCacheModule.forRoot({ ttl: Number(process.env.REDIS_DEFAULT_TTL), }),
TypeScript
복사

ElastiCache Redis 사용 시 만나게 되는 Timeout

ElastiCache로 Redis를 클라우드 환경에서 운영중이고 로컬개발환경이라면 아래와 같이 타임아웃을 만나게된다.
이는 ElastiCache의 정책으로 접속IP가 보안그룹에 속해있다고해도 외부에선 접속 할 수 없고 동일한 VPC에서만 접근이 가능하도록 강제되어 있어 이 설정을 변경 할 수 없으므로 Site-to-Site VPN(IPSEC VPN)을 설정을 진행하거나 근무장소가 지속적으로 바뀌거나 재택환경이라면 Client VPN(SSLVPN)을 사용해야한다.
아래 링크를 통해 해당 문제를 해결하고 진행한다.

REDIS-CLI 접속 및 명령어 확인

# vpn 연결 후 redis 접속 redis-cli -h clustercfg.tirepick-redis-dev.fohfjl.apn2.cache.amazonaws.com -p 6379 # 현재 keys 조회 clustercfg.tirepick-redis-dev.fohfjl.apn2.cache.amazonaws.com:6379> keys * 1) "OrderItemReviewService.findOrderItemReviewAverageScoreByGroup.BATTERY" 2) "RepairShopReviewService.findRepairShopReviewAverageScore.36"
Bash
복사
VPN 연결 후 로컬 테스트 시 Redis 연결이 잘 되는 것을 확인할 수 있다.