The open source, in-memory data store used by millions of developers as a database, cache, streaming engine, and message broker.
in-memory 데이터 저장소. Key-Value 형태로 데이터를 저장하며 string, list, hash, set, sorted set 등 다양한 데이터 구조를 지원.
Redis는 데이터베이스, 캐시, 메시지 브로커 등 여러 목적으로 사용된다.
그 외 많은 정보들이 있지만 다음 기회에 천천히 알아보고 단순히 데이터베이스에서 데이터에 접근하는 상황과 외부 API 호출 시에 사용했을 때 성능 차이가 있는지를 비교해 보고자 했다.
Redis를 사용하기 위해 Docker image 파일을 다운 받아 실행시킨다.
$ docker pull redis:alpine
$ docker run --name redis-test -d -p 6379:6379 reids:alpine
$ docker exec -it redis-test /bin/sh
$ redis-cli
위 명령어를 모두 입력하면 redis 명령어를 사용할 수 있다.
데이터를 Key-Value 형태로 캐싱하고 해당 데이터를 Key를 활용하여 꺼내오는 예제를 따라 해보았다.
> SET user:1 salvatore
> GET user:1
예제를 살펴보니 해당 데이터의 만료 기간도 정할 수 있다.
> EXPIRE user:1 1
user:1이라는 키를 가지는 데이터의 만료 기간을 1초로 정해준 것이다. 1초 후 해당 키를 넣어 GET 요청하면 nil이 반환되는 것을 볼 수 있다.
다음과 같은 구조로 api 서버를 구성했다.
데이터베이스에서의 데이터 접근과 외부 api를 통한 데이터 요청에 대한 테스트를 진행했다.
Server: Go (net/http)
DB: Postgres:14-alpine
Cache DB: Redis:alpine
External API: https://quotation-api-cdn.dunamu.com/v1/forex/recent?codes=FRX.KRWUSD
3개의 도커를 활용하여 해당 테스트를 진행했다. docker-compose.yml 파일은 다음과 같이 작성하였다.
services:
web:
build:
context: .
dockerfile: api.Dockerfile
ports:
- 9090:9090
environment:
PORT: 9090
REDIS_URL: redis
POSTGRES_URL: postgres
redis:
image: redis:alpine
postgres:
build:
context: .
dockerfile: postgres.Dockerfile
Go로 작성한 서버에서 redis와 postgres 컨테이너에 접근하기 위해 환경 변수에 각각의 service name을 적어주었다. 또한 postgres 컨테이너가 빌드 됨과 동시에 디비에 원하는 데이터를 삽입해놓기 위해 api.Dockerfile과 postgres.Dockerfile을 따로 작성하였다.
/db?codes=KRWUSD
경로로 다음과 같은 GET 요청을 받으면 데이터베이스에 삽입된 KRWUSD에 대한 정보를 가져온다./api?codes=KRWUSD
경로로 다음과 같은 GET 요청을 받으면 외부 API를 호출하여 KRWUSD에 대한 정보를 가져온다.두 테스트 모두 Redis에서 Get요청에 실패(cache miss)하면 데이터베이스 또는 API를 호출하도록 하였다.
결과는 다음과 같다.
Go 언어에서의 Marshal과 Unmarshal 과정이 포함되어 있긴 하지만 결과에 유의미한 영향을 줄 것 같지 않았다. (진짜 그런지 확인해 보고 싶어서 Go 언어에서의 해당 과정에 대해 알아보고 글을 작성하려고 한다.)
실무나 실제 운영되고 있는 서비스에서 해당 결과의 차이가 유의미 한지는 모르겠으나 단순 수치로만 봤을 때는 굉장히 효과가 있는 것으로 보였다.
캐싱 전략을 잘 세운다면 Redis를 활용하여 api 서버의 성능을 더욱 올릴 수 있을 것 같다.
Reference: