본문 바로가기
Project/MUNGCHI

#3 한시간 단위로 집계해서 Redis에 캐싱하기

by developerBeluga 2023. 11. 10.
728x90
반응형

 

 

 

 

 

뭉치에서 특정 작품의 전체 타래를 볼 수 있는 서비스를 만드려고 한다.

타래는 n개의 작품 별로 n회차마다 n개가 있다.

...(긁적)

 

그렇다보니 클라이언트의 요청이 있을 때마다 그 많은 데이터를 헤집고 쪼개고 붙이는 짓을 하기엔 자원이 많이 소비된다.

그래서 1시간 단위로 집계해 캐싱하는 방법을 택하게 방법을 선택했다.

Redis 안쓰겠다고 요리조리 피했는데 결국엔 쓰고야 마는구만 👀

 

 

 

 

NodeJS에서 Redis 사용하기

brew install redis

// 다운로드 후 시작하기
brew services start redis

맥이니깐 brew로 Redis로 깔아보도록 하자.

start해서 successfully가 나오면 된거다.

굳 👍

 

NodeJS에서 Redis 사용하기 위해서는 npm install redis를 해줘야 한다.

 

import { createClient } from 'redis'
export const redisClient = createClient({
  url: 'redis://localhost:6379'
})
redisClient.connect()
redisClient.on('connect', () => console.log('redis connect success'));
redisClient.on('error', (err) => console.error('redis error', err));

 

app.ts 혹은 가장 위인 상위 파일에 redis를 연결해주는 코드를 넣어주자.

 

 

 

MongoDB Aggregate 사용하기

작품별 회차마다 가장 인기 많은 데이터를 계산해야하는데 조건이 무려 3개나 된다.

1) 작품별

2) 회차마다

3) 가장 인기 많은

데이터를 어떻게 구할 수 있을까?

 

MongoDB Aggregate를 사용하면 된다!

(MongoDB를 사용할 경우)

 

 

https://www.mongodb.com/docs/manual/aggregation/

여러문서를 처리하기에 최적화된 Aggregation은 그룹화를 통해 단일 결과를 반환한다.

그렇기 때문에 조건이 복잡하다 싶으면 Aggreation Pipeline들을 이용하면 된다.

더 자세히 알고 싶은 사람은 아래 사이트 참고

https://www.mongodb.com/docs/manual/core/aggregation-pipeline/

 

Aggregation Pipeline — MongoDB Manual

Docs Home → MongoDB Manual An aggregation pipeline consists of one or more stages that process documents:Each stage performs an operation on the input documents. For example, a stage can filter documents, group documents, and calculate values.The documen

www.mongodb.com

 

 

    import { redisClient } from "../../app";
    const result = await Thread.aggregate([
      // 작품별, 회차별로 가장 인기 많은 타래 집계
            {
              $sort: {
                "good": -1,
                "_id": 1 
              }
            },
            {
              $group: {
                _id: { works: "$works", time: "$time" },
                docs: { $push: "$$ROOT" }, 
                maxGood: { $max: "$good" }
              }
            },
            {
                $project: {
                docs: 1,
                maxGood: 1
                }
            }
    ]);

    await redisClient.set('aggregate:thread', JSON.stringify(result));

$sort, $group, $project을 사용했다.

$sort는 결과 문서를 정렬한다.

$group은 지정된 키로 문서를 그룹핑하고, 각 그룹에 대한 다양한 연산을 수행한다.

$project는 결과 문서의 형태를 변형하거나 필드를 추가, 제거한다.

 

Aggregation을 이용해 손쉽게 내가 원하는대로 데이터를 조합했다.

마지막에 Redis에 저장해주면 된다.

 

 

 

 

스케줄러 이용해서 매시 정각마다 집계하기

import schedule from 'node-schedule';
import { aggregateAndCache } from '../routes/';

export const startScheduler = () => {
    // 서버 시작 할 경우 바로 집계
    aggregateAndCache()

    // 매시 정각마다 집계
    schedule.scheduleJob('0 * * * *', aggregateAndCache)
}

처음엔 node-schedule을 이용해서 집계했다.

 

 

https://npmtrends.com/agenda-vs-cron-vs-later-vs-node-cron-vs-node-schedule

하지만 비교해본 결과 cron이 스케줄러 중에서 가장 인기가 많다는 걸 알았다.

주간 다운로드 수도 백만을 넘기 때문에 냉큼 넘어갔다.

 

import corn from 'node-cron';
import { aggregateAndCache } from '../routes/';

export const startScheduler = () => {
    // 서버 시작 할 경우 바로 집계
    aggregateAndCache()

    // 매시 정각마다 집계
    corn.schedule('0 * * * *', () => {
        console.log('[info] schedule running')
        aggregateAndCache();
    }, {
        scheduled: true,
        timezone: "Asia/Seoul"
    })
}

timezome을 설정할 수 있는게 좋았다 👍

스케줄러를 써야 한다면 corn을 쓰는걸 추천한다.

 

 

 

 

Redis에 저장된 데이터 확인하기

redis-cli

get [설정한 이름]

터미널에서 간단하게 Redis 데이터를 확인할 수 있다.

set으로 저장한 이름을 get할 때 사용하면 된다.

 

잘 나온 것을 확인할 수 있다.

하지만 터미널에서 확인하기 매우 불편하기 때문에 툴을 사용하기로 했다.

 

무려 앱스토어 개발자도구 차트 무료와 유료를 차지하는게 Redis 보는 툴이다 🤣

우선 무료인 Medis를 사용하도록 하자.

 

커넥트 해주니 바로 들어올 수 있었다.

데이터도 예쁘게 잘 보여주니 만족스럽다 👍

 

 

 

 

 

 

 

728x90
반응형

댓글