AWS

[Redis] AWS ElasticCache Redis 사용하기 - Node JS, EC2, RDS(mysql), Lambda

폭풍저그김탁구 2022. 9. 19. 17:42

 

지금까지는 항상 DB에서 조회한 데이터를 사용했다. 하지만 캐싱을 적절히 사용한다면 실시간으로 데이터를 업데이트 해줄 수 있고 속도도 향상시킬 수 있기 때문에 캐시를 사용하려고 한다.

 

지금 AWS로 서비스를 하고 있기 때문에 Elastic Cache의 Redis를 처음 도입하고 사용하는 것까지 다뤄보려 한다.

 

 

 


 

 

1. Redis

나는 간단하게 '캐싱용 DB'라고 이해했다. 데이터베이스에 저장된 데이터를 메모리 캐시로 임시로 저장하는 것이다. 

메모리로만 데이터를 처리하기 때문에 데이터 저장 및 검색 속도가 매우 빠르다는 장점이 있다.

Redis를 왜 써야 하고, 무슨 이정이 있는지는 참고자료나 다른 블로그를 보는 게 더 좋을 것 같다.

 


 

 

 

2. 클러스터 생성

AWS 콘솔에서 Elastic Cache에 접속해주고 Redis 클러스터를 생성해준다. 나는 기본 설정들은 웬만해선 따랐고, 노드 유형은 cache.t3.medium으로 설정했다.

클러스터 생성 후 Redis용 보안 그룹도 생성해준다. EC2에서 설정할 수 있고, 자세한 과정은 참고자료를 확인해보시면 됩니다.

 

 

+) 비밀번호 생성하는 법

AWS 콘솔에서 ElasticCache > 사용자 관리 > 사용자 생성

> 사용자 ID는 원하는 걸로, 사용자 이름은 default로 하고, 암호 설정해서 생성

>사용자 그룹 > 사용자 그룹 생성

> 방금 생성한 사용자 추가해서 생성

 

redis 클러스터 생성 시

고급 설정 > 보안 > 전송 중 데이터 암호화 '사용' > 액세스 제어 > 자용자 그룹 액세스 제어 목록 > 방금 생성한 사용자 그룹으로 설정해서 클러스터 생성하면 된다.

 

 


 

 

3. 생성 확인 - 노드에 연결

이 과정은 꼭 하지 않아도 된다. 하지만 확인 용으로 해보는 걸 추천.

 

먼저 EC2에 연결한다. 나는 aws 콘솔에서 바로 웹으로 접속했다.

그리고 gcc를 깔아주고 redis-cli도 깔아준다.

(이때 ec2랑 redis에서 보안그룹 설정할 때 6379 포트에 대해 접근 허용을 해줘야 한다. 또 같은 VPC 내에서 EC2를 돌리고 있는지도 확인할 것) 

아래 독스 참고하면서 따라하기.

https://docs.aws.amazon.com/ko_kr/AmazonElastiCache/latest/red-ug/nodes-connecting.html

 

노드에 연결 - Amazon ElastiCache for Redis

이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.

docs.aws.amazon.com

 

이때 나처럼 암호화를 했다면

https://docs.aws.amazon.com/ko_kr/AmazonElastiCache/latest/red-ug/in-transit-encryption.html#in-transit-encryption-enable

이 독스의 연결 방식을 따라하면 된다. 오류가 생긴다면 이 블로그의 다른 글에 내 삽질기를 써놨으니 참고..ㅜ

 

 

 


 

 

4. lambda와 연결 확인

typescript로 작성하였고 nodejs로 캐시를 구현하겠다.

 

우선 Lambda에서 Redis로 연결하려면 같은 VPC 내에 있어야 한다. (참고 자료)

 

VPC에 추가해주려면

The provided execution role does not have permissions to call CreateNetworkInterface on EC2

 

이런 에러가 뜨므로, 그 전에 Lambda를 배포한 Role에 규칙을 추가해준다. (참고 자료)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeNetworkInterfaces",
        "ec2:CreateNetworkInterface",
        "ec2:DeleteNetworkInterface",
        "ec2:DescribeInstances",
        "ec2:AttachNetworkInterface"
      ],
      "Resource": "*"
    }
  ]
}

 

같은 VPC내에 넣어줬으면 배포하고 확인해보자.

 

코드는 다음과 같다. 클라이언트 생성 부분은 모듈화 해주는 걸 추천.

import { createClient } from 'redis';

export default async () => {
  try {

    const client = createClient({
      url: `redis://${process.env.REDIS_USERNAME}:${process.env.REDIS_PASSWORD}@${process.env.REDIS_HOST}:${process.env.REDIS_PORT}`,
      legacyMode: true,
      socket: {
        tls: true,
      },
    });

    client.on('connect', () => {
      console.info('*Redis connected!');
    });
    client.on('error', (err) => console.log('*Redis Client Error', err));
    client.on('end', () => console.log('*Redis Client end'));

    await client.connect();

    await client.v4.set('key', 'val');
    let value = await client.v4.get('key');
    await client.v4.quit();
    return value;
  } catch (err) {
    throw new Error(`${err})`);
  }
};

 

 

> 삽질 기록

더보기

lambda nodejs aws redis 조합은 너무 찾기 힘들었어서 삽질이 많았다..

일단 문제가 생기면 이게 node 문제인지 aws 문제인지 redis 문제인지 알기가 너무 어려웠음 ㅜㅜ...

사실 결국 내 문제였다.

 

1. tls 연결

암호화 걸어놓은 redis 클러스터에 연결하려면 tls설정을 true로 바꿔줘야 한다. 

파라미터 양식 및 종류는 redis의 npm 독스를 확인해보자.

참고로 저 host는 위에서 연결했듯이 aws 콘솔에서 확인할 수 있다. (기본 엔드포인트 항목 복사해서 뒤에 :6379 날리기)

 

2. 프로미스 기반 설정

자꾸 set을 기다리지 않고 get을 하는 문제가 발생했다. 이때는 v4 버전을 사용하면 된다. (legacy 모드 설정해야 사용 가능)

하지만 실제 상황에서 get을 하고 바로 set을 하는 경우가 있을까...? 싶긴 하다.

 

3. connection 끊기

마지막에 quit을 해줘야 함수가 끝난다. 커넥션이 안 끊어지니까 자꾸 timeout이 떴음.

이때도 v4로 quit을 해줘야 순서대로 잘 끝난다.

그냥 클라이언트에 quit을 해줘서 자꾸 set 하기도 전에 quit해버리는 불상사가 발생했음..ㅜㅜ

 

 


 

 

5. 로직 구성

Cach-Aside 방식으로 구현했습니다.

아래는 수도 코드입니다.

      const isCached = await client.v4.get(key);
      if (isCached) {
        //Cache hit
        return JSON.parse(isCached);
      } else {
        //Cache Miss
        const val = await connection.query(`SELECT * (...)`);
        await client.v4.set(userId, JSON.stringify(val));
      }

 

따로 해시로 저장하지 않고 그냥 스트링 자체로 묶어서 저장했습니다. 그리고 return할 때는 다시 파싱해주는 식으로 구현했습니다.

 

 

 

 

내가 무슨 부귀영화를 누리겠다고... 이 짓을 시작해서... ... ...

 

 

 

 

 


 

참고자료

https://minholee93.tistory.com/entry/AWS-ElastiCache-Redis-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

 

[AWS] ElastiCache Redis 사용하기

이번 글에서는 ElastiCache Redis 클러스터를 생성해보겠습니다. 0. ElastiCache란? 분산 인 메모리 캐시(In-Memory-Cache)를 손쉽게 생성하고 확장할 수 있는 서비스입니다. 읽기 중심의 서비스(소셜 네트워

minholee93.tistory.com

 

https://www.megazone.com/techblog_20200707_five-workload-characteristics-to-consider-when-right-sizing-amazon-elasticache-redis-clusters/

 

Amazon ElastiCache Redis 클러스터의 적절한 사이즈 선택을 위해 고려해야 할 5가지 워크로드 특성

오늘 메가존 테크블로그에선 Amazon ElastiCache 워크로드에 적합한 노드 크기 및 클러스터 토폴로지 결정 프로세스와 중요한 고려 사항에 대해 설명해드리도록 하겠습니다.

www.megazone.com

https://stackoverflow.com/questions/39595689/aws-lambda-and-redis

 

AWS Lambda and Redis

I'm trying to write an AWS Lambda function which uses redis(on amazon elasticcache). The problem – I can't connect to redis. I use code like this 'use strict' function handler (data, context, cb)...

stackoverflow.com

https://stackoverflow.com/questions/41177965/aws-lambdathe-provided-execution-role-does-not-have-permissions-to-call-describ

 

AWS Lambda:The provided execution role does not have permissions to call DescribeNetworkInterfaces on EC2

Today I have a new AWS Lambda question, and can't find anywhere in Google. I new a Lambda function, there is no question. But when I input any code in this function[eg. console.log();] and click ...

stackoverflow.com

https://inpa.tistory.com/entry/REDIS-NODE-%F0%9F%93%9A-%EB%85%B8%EB%93%9Cexpress%EC%97%90%EC%84%9C-redis-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%BA%90%EC%8B%B1-%EC%84%B8%EC%85%98-%EC%8A%A4%ED%86%A0%EC%96%B4

 

[REDIS] 📚 Node.js 에서 redis 모듈 사용법 (캐싱 & 세션 스토어)

Node 프로젝트에서 pm2로 다중 클러스터 인프라를 구축했다면 세션 불일치 문제가 생기게 마련이다. 만일 서버가 종료되어 메모리가 날라가면 접속자들의 로그인이 모두 풀려버리게 된다. 따라서

inpa.tistory.com

https://github.com/redis/node-redis/blob/HEAD/docs/client-configuration.md

 

GitHub - redis/node-redis: A high-performance Node.js Redis client.

A high-performance Node.js Redis client. Contribute to redis/node-redis development by creating an account on GitHub.

github.com