Redis

Vorhandenheit ·2022년 5월 6일
0

Redis

목록 보기
2/5

Redis(REmote Dictionary Server)

파이널 프로젝트 중에, 백엔드 sequelize와 api로 controller 작성 후, 뭘 더할께 없나 찾아보다가 redis라는 걸 알게되었습니다.
redis란 간단하게 말해서 빨리반응하기 위한 데이터베이스 입니다.
좀 더 디테일하게 들어가보겠습니다.

1. Redis 란?

데이터베이스가 있는데도 불구하고 이 redis를 사용하는 이유는, 데이터베이스 부담을 줄여주기 위해서입니다.

어떤 방식으로?

(1) 캐시

redis는 In-Memory 기반 입니다. 이 redis Cache는 여기에 위치합니다.
cache란 나중에 요청할 결과를 미리 저장해둔 후 빠르게 서비스해 주는 걸 의미합니다. 자주 사용하는 걸 cache에 저장함으로써, 데이터베이스의 부담을 줄여주고 더 빨리 반응해줄 수 있는 것입니다.

  • Look aside Cache 방법
  1. 클라이언트 요청을 받은 Web Server는 데이터가 존재하는 지 먼저 Cache를 확인합니다.
  2. Cache에 데이터가 있다면 Cache에서 가져옵니다.
  3. Cahce에 데이터가 없다면 DB에 가져온 후 Cache에 다시 저장합니다.
  • Wrtie Bck
    1. 클라이언트의 요청을 받은 Web Server는 모든 데이터를 Cache를 저장합니다.
  1. Cache에 특정 시간동안의 데이터를 저장합니다.
  2. Cache에 있는 데이터를 DB에 저장합니다.
  3. DB에 저장된 데이터를 삭제합니다.

write back은 INSERT 쿼리를 일일히 날리지않고 한꺼번에 처리하기위해 사용합니다. 예를 들어, 영어 듣기 평가를 진행하는 서비스 경우 여러 항시에 동시에 제출버튼을 눌렀을 때, DB에 갑작스럽게 엄청난 요청이 몰리면 DB서버에 부하가 발생하기 떄문에, write back장식을 사용해서 캐시 메모리에 데이터를 저장해놓고, 이후 DB에 디스크 업데이트 하는 것입니다.
DB에 접근하는 횟수가 줄어들지만, DB에 저장하기 전에 캐시 서버가 죽으면 데이터가 유실될 수도 있습니다.

(2) Collection

redis와 같이 꼭 나오는게 있는데 Memocache입니다. Memocached는 분산 메모리 캐싱 시스템입니다. Memocaced는 key-value 형태로 메모리에 저장히지만 redis는 Collection을 지원합니다.

  • String : 가장 일반적 형태로, key-value로 저장하는 형태입니다.
  • Set : 중보된 데이터를 담지 않기위해 사용하는 자료구조입니다.
  • List : Array 형식의 데이터 구조입니다. List를 사용하면 처음과 긑에 데이터를 넣고 빼는 건 속도가 빠르지만 중간에 데이터를 삽입하거나 삭제하는건 어려움이 있습니다.
  • Sorted Set: 유저 랭킹 보드서버 같은 구현에서 사용할 수 있습니다. 이때 데이터 삽입은 ZADD key 점수 value 명령어로 수행하고 정렬된 값은 zrange를 통해 가져올 수 있습니다.

이런 다양한 구조체를 지원함으로 DB, Cache, Message Queue, Shared Memory용도로 사용될 수 있습니다.

Redis와 Memocache 차이

2. 특징

  • 영속성을 지원하는 인 메모리 데이터 저장소
  • 다양한 자료구조 지원
  • 싱글 스레드 방식으로 인해 연산을 원자적으로 수행 가능
  • 읽기 성능 증대를 위한 서버 측 레플리케이션을 지원
  • 쓰기 성능 증대를 위한 클라이언트 측 샤딩 지원
  • redis의 데이터를 disk에 저장하는 방식은 snapshot, AOF 방식입니다.

AOF
Redis의 모든 write/update 연산 자체를 모두 log파일에 기록하는 형태입니다. 서버가 재시작 시 write/update를 순차적으로 재실행하고 데이터를 복구합니다.

Snapshot
RDB와 비슷하게 어떤 특정 시점의 데이터를 Dist에 담는 방식을 뜻합니다. Blocking 방식의 SAVE와 Non-blocking 방식의 BGSAVE 방식이 있습니다.

(1) 장점

  • 리스트 배열과 같은 데이터를 처리하는 데 유요합니다.
    - 리스트형 데이터 입력과 삭제는 Mysql 에 비해 10배 정도 빠르다고 합니다.
  • 메모리 활용하면서 영속적 데이터 보존이 가능합니다.
  • 스냅샷 (기억장치) 기능을 제공하여 메모리 내용을 *.rdb파일로 저장하여 해당 시점으로 복구 할 수 있습니다.
  • Redis Server는 1개의 싱글 쓰레드로 수행되며, 따라서 서버 하나에 여러개의 서버를 띄우는게 가능합니다.

(2) 단점

  • In-memory 방식이기 떄문에 장애 발생시 데이터 유실이 발생합니다.
    => 영속적 데이터 보존을 위해서는 스냅샷과 AOF 기능을 통한 복구방식을 주의해서 작성해야합니다.

AOF
Redis의 모든 write/update 연산 자체를 모두 log파일에 기록하는 형태

  • 대규모 데이터에 대한 응답 속도의 불안정성

3. Redis 아키텍처

(1) Standalone : No HA, 마스터

  • 레디스 서버 1대로 구성하며 이를 마스터 노드라고 합니다.
  • 서버 다운시 AOF 또는 Snapshot 파일을 이용해 재시작합니다.

(2) Replication : Half HA, Master-slave

  • 레디스 서버 2대(master-slave)로 구성됩니다. 슬레이브는 마스터의 데이터를 실시간으로 전달받아서 보관합니다.
  • 마스터 다운시 슬레이버 서버를 통해 서비스를 계속할 수 있습니다.
  • 한 마스터에 슬레이브를 여러대 구성할 수 있습니다.

(3) 이중화 + 센티널(Sentinel) : HA, 무중단 서비스 가능

  • 마스터-슬레이브 구성에 센티널을 추가해서 각 서버를 감시하도록하며, 센티널은 마스터 서버를 감시하고 있다가 다운되면 슬레이브를 마스터로 승격시킵니다.
  • 다운된 마스터가 복구되면 센티널이 슬레이브로 전환시킵니다.
  • 레디스 마스터 노드가 모든 데이터를 가지고 있으며 슬레이브는 마스터에 대한 복제본을 유지하고 있으며, 데이터를 분산하지 않습니다
  • 일반적으로 레디스 센티널은 레디스 서버마다 하나씩 설치하고, 레디스 서버와 분리된 프로세스이며 다른 포트를 사용합니다.

(4) 레디스 클러스터(Cluster) : HA, 무중단 서비스 가능

  • 각 마스터 서버는 데이터 처리와 센티널의 역할을 같이 수행합니다.
  • 1번 마스터 서버가 다운되면 나머지 살아있는 마스터 중에서 리더를 선출해서 리더가 1번 마스터의 슬레이브를 마스터로 승격시킵니다
  • 마스터 서버는 최소 3대로 구성하고 각각의 슬레이브를 가집니다.

4. 사용

(1) 기본

  • redis 설치
npm i redis
  • Redis 서버 연결
const express = require('express');
const redis = require('redis');
const axios = require('axios');
const bodyParser = require('body-parser');

// 서비스 포트 선언
const port_redis = 6379;
const port = 3005;

// Redis 포트를 6379로 설정
const redis_client = redis.createClient(port_redis);

// express 서버 설정
const app = express();

// Body Parser 미들웨어
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

// express 서버를 3005번 포트로 실행;
app.listen(port, () => console.log(`Server running on Port ${port}`));

createClient메서드는 RedisClient 객체를 생성합니다. redis서버와 express 서버가 같은 호스트라면 createClient()에 별도의 설정을 해주지않아도 됩니다. 만약 호스트가 다르다면 포트 번호드의 설정을 추가해야합니다.

  • 미들웨어 설정
checkCache = (req, res, next) => {
  redis_client.get(req.url, (err, data) => {
    if (err) {
      console.log(err);
      res.status(500).send(err);
    }
    // Redis에 저장된게 존재한다.
    if (data != null) {
      res.send(data);
    } else {
      // Redis에 저장된게 없기 때문에 다음 로직 실행
      next();
    }
  });
};

미들웨어 형태로 만들어서 매 요청마다 캐시가 있는지 없는지 체크하여 Redis 값을 꺼내어 줄 수 있습니다.

(2) express-session 사용할 때

  • 설치
express-session
connect-redis
  • session 설정
const session = require('express-session');
const redis = require('redis');
const redisStore = require('connect-redis')(session);
const client = redis.createClient();

app.use(session({
    store: new redisStore({
        client: redis,
        host: 'localhost',
        port: 6379,
        prefix : "session:",
        db : 0,
        saveUninitialized: false,
        resave: false
    }),
    secret: "secret_key",
    cookie: { maxAge: 3000 }
}));
client.set('key', 'value');
client.get('key', (err) => {
});

set으로 설정하고 get으로 key-value값을 가져올 수 있습니다.

출처

https://velog.io/@hyeondev/Redis-%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C
https://rlawls1991.tistory.com/entry/Redis%EB%9E%80
https://steady-coding.tistory.com/586
https://goodgid.github.io/Redis/
https://haeunyah.tistory.com/78
https://charming-kyu.tistory.com/37
https://azderica.github.io/01-db-nosql-redis/

profile
읽고 기록하고 고민하고 사용하고 개발하자!

0개의 댓글