Redis

Jiwon Youn·2021년 4월 1일
0

Redis (Remote Dictionary Server)

  • 인메모리 기반의 키-값 구조 데이터 관리 시스템
  • NoSQL (비관계형 데이터베이스)
  • 영속성을 지원하는 인메모리 데이터 저장소
  • String, List, Hash, Set, SortedSet과 같은 다양한 데이터형을 지원

💡 NoSQL (Not Only SQL, 비관계형 데이터베이스)
많은 양의 데이터를 효율적으로 처리해야 할 때, 데이터의 분산처리, 빠른 쓰기 및 데이터의 안정성이 필요할 때 사용한다. 특정 서버에 장애가 발생했을 때에도 데이터 유실이나 서비스 중지가 없는 형태의 구조이기 때문에, NoSQL을 사용한다.
NoSQL에서는 테이블(Table)을 컬렉션(Collection)으로, 레코드(Record)를 문서(Document)로 부른다. SQL에서는 정해진 스키마를 따르지 않는다면 데이터를 추가 할 수 없었지만, NoSQL에서는 다른 구조의 데이터를 같은 컬렉션(=SQL에서의 table)에 추가할 수 있다.


Redis의 장점

  • 리스트, 배열과 같은 데이터를 처리하는데 유용하다.
  • 리스트형 데이터 입력과 삭제가 MySQL(RDBMS)에 비해서 10배 빠르다.
  • 여러 프로세스에서 같은 key에 대한 데이터 갱신을 요청할 경우, 데이터 부정합 방지 Atomic 처리 함수를 제공한다.
  • 명령어로 명시적으로 삭제, expires를 설정하지 않으면 데이터가 삭제되지 않는다.
  • 메모리의 내용을 *.rdb 파일로 저장해 스냅샷(기억장치) 기능을 제공한다. (해당 시점으로 복구 가능)
  • 데이터 분실 위험을 방지하는 Replication(Master-Salve) 방식을 제공한다.

💡 Redis Replication(데이터 복제) 설정 과정

  • Secondary에 replicaof 명령을 전달
  • Secondary는 Primary에 sync 명령 전달
  • Primary는 현재 메모리 상태를 저장하기 위해 Fork
  • Fork한 프로세서는 현재 메모리 정보를 disk에 dump
  • 해당 정보를 Secondary에 전달
  • Fork 이후의 데이터를 Secondary에 계속 전달

Redis의 단점

  • 메모리 사용량이 많음
  • Cache 및 Redis Session 등 관리 포인트가 늘어남
  • 스냅샷을 추출하는데 시간이 오래걸리며 스냅샷 추출된 후 서버가 다운되면 스냅샷 추출 이후 데이터는 유실 (백업 시점의 데이터만 유지)
  • 백업시 Fork()로 자식 프로세스를 생성해서 백업 작업을 수행하는데 이때 데이터가 크다면 순간적으로 CPU 부하가 발생

Redis 사용처

  • 인증 토큰 등을 저장(String 또는 Hash)
  • Ranking 보드로 사용 (Sorted Set)

메모리 관리

  • Physical 메모리 이상을 사용하면 문제가 발생
    → Swap이 있다면 사용하나 해당 메모리 page 접근 시마다 속도가 저하
    → 빠른 속도가 장점인 인메모리를 사용하는 의미가 없음
  • 큰 메모리를 사용하는 insatance 하나보다는 적은 메모리의 instance 여러 개가 안전함

Redis는 Single Thread

  • 동시에 하나의 명령만 처리할 수 있음
  • 단순한 get/set의 경우 초당 10만 TPS 이상 가능
  • Get All Collection과 같이 전체 데이터를 조회할 때 데이터 양이 많은 경우 속도 저하
    scan 명령으로 KEYS와같이 긴 명령을 짧은 여러번의 명령으로 대체 가능
  • Collection의 모든 item을 가져오고 싶을 때
    → 큰 Collection을 작은 여러 개의 Collection으로 나눠서 저장
  • redis.conf 권장 설정
    KEYS와 같은 특정 command disable

Docker Redis 사용하기

설치
$ docker pull redis

시작하기
$ docker run --name some-redis -d -p 6379:6379 redis
기본 포트인 6379에서 실행

Redis with NestJS

$ npm i --save redis


redis-module.ts

import { CacheModule, Global, Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { RedisCacheService } from './redis-cache.service';
import * as redisStore from 'cache-manager-redis-store';

@Global()
@Module({
  imports: [
    CacheModule.registerAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: async (configService: ConfigService) => {
        return {
          store: redisStore,
          host: configService.get('REDIS_HOST'),
          port: Number(configService.get('REDIS_PORT')),
          ttl: Number(configService.get('CACHE_TTL')),
          password: configService.get('REDIS_PASSWORD'),
        };
      },
    }),
  ],
  providers: [RedisCacheService],
  exports: [RedisCacheService],
})
export class RedisCacheModule {}
  • module에 config 설정
  • providers, exports : RedisCacheService
  • app.module.ts에서 RedisCacheModule imports

redis-service.ts

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

@Injectable()
export class RedisCacheService {
  constructor(@Inject(CACHE_MANAGER) private readonly cache: Cache) {}

  async get(key) {
    return await this.cache.get(key);
  }

  async set(key, value) {
    await this.cache.set(key, value);
  }
}

RedisCacheService에서 get, set 사용


0개의 댓글