[서버 성능 개선 스토리 #2] 캐시와 Redis 알아보기
일반적으로 요청-응답 시 데이터베이스에 접근할 때 가장 많은 시간이 소요된다고 한다. 그리고 지금 내가 진행중인 프로젝트는 WEB-WAS-DB의 3티어 구조이다. 사용자가 많이 늘어나 DB에 무리가 갈 것을 사전에 방지 하고자 캐시를 활용해 서버 성능을 개선 시켜 보려고 한다.
Cache
- 캐시는 데이터나 값을 미리 복사해 놓는 임시 장소를 가리킨다.
- 캐시는 보통 메모리를 사용하기 때문에 속도가 상당히 빠르다.
- 캐시에 데이터를 미리 복사해 놓으면 계산이나 접근 시간 없이 더 빠른 속도로 데이터에 접근할 수 있다.
- 즉, 미리 결과를 저장하고 나중에 요청이 오면 그 요청에 대해서 DB에 접근하지 않고 Cache에 요청을 처리한다.
- 캐시는 데이터나 값을 미리 복사해 놓는 임시 장소를 가리킨다.
- 캐시는 보통 메모리를 사용하기 때문에 속도가 상당히 빠르다.
- 캐시에 데이터를 미리 복사해 놓으면 계산이나 접근 시간 없이 더 빠른 속도로 데이터에 접근할 수 있다.
- 즉, 미리 결과를 저장하고 나중에 요청이 오면 그 요청에 대해서 DB에 접근하지 않고 Cache에 요청을 처리한다.
이렇게 유용하게 쓰이는 캐시에도 단점이 존재한다고 한다. 캐시 서버는 속도를 위해서 주로 메모리를 사용하기 때문에 서버에 장애가 생기면 메모리가 날라가서 데이터가 손실될 수 있다. 그래서 때로는 디스크를 사용하도록 구성하거나 무분별한 캐시 사용은 피해야 겠다.
Redis
- Redis(Remote Dictionary Server)는 "키-값" 구조의 비정형 데이터를 저장하고 관리하기 위한 오픈소스 기반의 비관계형 데이터베이스 관리 시스템(DBMS)이다.
- 모든 데이터를 메모리로 불러와서 처리하는 메모리 기반 DBMS이다.
- Redis가 지원하는 데이터 구조
- String
- List
- Set
- Sorted
- Set
- Hashes
Redis 설정
Redis 설치(Mac)
- Redis(Remote Dictionary Server)는 "키-값" 구조의 비정형 데이터를 저장하고 관리하기 위한 오픈소스 기반의 비관계형 데이터베이스 관리 시스템(DBMS)이다.
- 모든 데이터를 메모리로 불러와서 처리하는 메모리 기반 DBMS이다.
- Redis가 지원하는 데이터 구조
- String
- List
- Set
- Sorted
- Set
- Hashes
Redis는 Homebrew를 사용하여 Mac에 설치할 수 있다.
brew install redis
Redis 시작
다음 명령어를 실행하여 Redis 서버를 로컬로 시작할 수 있다.
redis-server
NodeJS 프로젝트 설정
종속성 설치
Redis에 연결하기 위해 redis 의존성을 설치한다.
npm install redis
만들어 놓은 서버와 Redis 서버를 연결
server.js
const express = require('express');
const redis = require('redis'); // Redis 모듈 불러오기
const axios = require('axios');
const bodyParser = require('body-parser');
const redisClient = redis.createClient();
// ...
createClient() 메서드는 새로운 RedisClient 객체를 생성하는데, redis 서버와 express 서버가 같은 호스트에서 돌아가고 있다면 createClient() 에 별도의 설정을 해 주지 않아도 된다. 만약 호스트가 다르다면 호스트 url, 포트 번호 등의 설정을 추가해주어야 한다.
//...
app.get('/photos', async(req, res) => {
const albumId = req.query.albumId
const {data} = await axios.get(
'https://jsonplaceholder.typicode.com/photos',
{params : {albumId}},
)
res.json(data)
})
//...
Json api를 테스트해볼 수 있는 사이트를 통해 데이터가 큰 "/photos"를 보내달라고 요청해봤다.
응답에 걸리는 시간은 0.4초. 자 그럼 동일한 요청이 들어올 경우 캐시를 반환 하도록 수정해보자.
//...
// 캐시 체크를 위한 미들웨어
checkCache = (req, res, next) => {
redisClient.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();
}
});
};
app.get('/photos', checkCache, async (req, res) => {
try {
console.log(req.url)
const {data} = await axios.get('https://jsonplaceholder.typicode.com/photos');
await redisClient.setex(req.url, 1440, JSON.stringify(data));
return res.json(data);
} catch (error) {
console.error(error);
return res.status(500).json(error);
}
});
//...
- 우선, '/photos'로 요청이 들어오면 "checkCache" 미들웨어에서 Redis 서버에 해당 데이터가 캐싱되어 있는지 확인한다.
- RedisClient객체의 get 메서드는 첫 번째 인자로 key 값을 받고, 두 번째 인자로 콜백 함수를 전달받는다.
- 이 경우 '/photos'로 저장되어 있는 value가 있는지 확인하고, 캐시값이 존재한다면 해당 데이터를 보여준다.
수정이 됐다면 잊지말고 Redis 서버도 실행시킨 후 다시 요청을 보내보자.
동일한 요청을 반복해서 보내는 경우 응답 시간은 0.03초. 첫 번째 요청과 비교하면 매우 빨라진 것을 확인할 수 있었다.
이렇게 Redis를 통해 캐시를 활용해봤다. 잘 활용하면 애플리케이션의 속도와 성능을 크게 증가시키는 역할을 할 수 있겠다. 적절한 api에 적용 후 서버 부하 테스트를 다시 돌려서 향상된 성능을 직접 느껴봐야겠다.
참조
https://redis.io/docs/about/
https://ko.wikipedia.org/wiki/%EC%BA%90%EC%8B%9C
https://sabarada.tistory.com/103
https://brunch.co.kr/@jehovah/20
https://charming-kyu.tistory.com/37
Author And Source
이 문제에 관하여([서버 성능 개선 스토리 #2] 캐시와 Redis 알아보기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@onady/서버-성능-개선-스토리-2-캐시와-Redis-알아보기저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)