Study Note
Redis

[스터디 8주차] Redis

  • 주제 : 자유주제 발표
  • 일시 : 2022년 5월 12일 ~ 6월 9일

1. 캐시에 대해서

캐시가 뭐지?

보통 크롬이 좀 이상하거나 하면 방문기록, 쿠키, 캐시 삭제 같은 걸 하곤 한다. 여기서 캐시는 웹사이트에 들어가며 컴퓨터 안에 다운로드받은 이미지나 자바스크립트 파일같은걸 로컬에 저장해둔 걸 의미한다. 처음에 웹사이트에 들어갔을 때 10mb의 이미지를 다운받았고, 새로고침을 할 때도 똑같이 10mb의 이미지를 다운받는다면, 새로고침 몇 번에 수백mb의 데이터를 쓰게 될 것이다.

캐시가 왜 필요할까?

이처럼 로컬에 데이터를 저장해뒀다가 뽑아서 쓰면 데이터 전송량도 줄이고, 웹사이트의 성능 개선까지 얻을 수 있다. 그래서 브라우저 단에서는 이렇게 기본적으로 캐시를 사용하게 된다. 그런데 서버에서는 캐싱을 어떻게 할까?

하루에 한 번 업데이트되는 게임 순위 랭킹표가 있다고 하자. 전체 10만명의 이용자 중에 상위권 랭커 탑 100명을 뽑아서 보여주는 API를 만들어야된다고 할 때, 매 요청마다 아래와 같이 DB 쿼리를 날리면 부하가 어마어마하게 클 것이다.

SELECT u.name, s.score FROM user u JOIN score s ON u.idx = s.user_idx ORDER BY s.score DESC LIMIT 100

이 때 조회해서 나오는 쿼리 결과값을 JSON으로 만들어 저장해뒀다가, API에 요청이 들어오면 저장해둔 JSON r값을 리턴해주고, 하루에 한 번씩 캐시를 업데이트해주기만 한다면 DB 서버의 부하가 엄청나게 줄어들 것이다.

여기서 캐싱에 사용되는 것이 바로 Redis다. DB 서버의 부하를 줄여주고 빠르게 결과값을 리턴해주어 성능까지 개선되는 효과를 볼 수 있다.

2. AWS 이야기

ElastiCache는?

AWS에서 제공하는 완전관리형 인메모리 캐시 서비스이다. HDD와 SSD, RAM 중에 가장 빠른 것은? RAM이 제일 빠르다. Redis는 데이터를 메모리(RAM)에 저장한다. 그래서 인메모리 캐시 서비스라고 부른다. 그런데 메모리는 잘 알다시피 휘발성이라는 특성을 가지고 있다. 물론 캐시는 잠깐 저장해두고 성능 개선을 위해 호출해서 갖다 쓰는거고, 중요한 데이터는 대부분 DB에 있을테니 인메모리 서비스인 것이 크게 문제가 되지는 않는다. 하지만 옵션으로 파일에 데이터를 쓰는 기능도 제공해 데이터가 날아가지 않게 할 수도 있다.

ElastiCache는 이런 Redis를 복잡한 설치와 세팅 과정 없이 버튼 클릭 몇 번으로 사용할 수 있게 만들어준다. 또 Redis 서버 여러 대를 띄우고, 확장하고, 장애가 났을 때 대응하는 것까지 모두 AWS에서 처리해주니 실무에서는 대부분 Redis를 ElastiCache와 활용하는 경우가 많다. 또 Memcached라는 캐시 서비스도 제공해준다.

VPC는 무엇이고, 왜 ElastiCache는 VPC 내부에서만 접속이 가능할까?

VPC는 Virtual Private Cloud의 줄임말. 가상 사설 클라우드라는 말은, 외부와 분리된 내부망에서 여러 클라우드 서비스들을 이용할 수 있게 울타리를 둘러둔 것이라고 이해하면 된다. 일반적으로 EC2나 RDS 인스턴스를 올리면 인바운드/아웃바운드 트래픽의 접근권한을 제어할 수 있는 보안그룹(SG)을 설정하게 된다. 이 SG가 방화벽 역할을 하여 특정 IP 대역에서만 서버에 접속할 수 있도록 제어하게 된다. 그런데, EC2나 RDS는 VPC 외부에서 접속을 받을 수 있다. 다시 말해 인바운드 설정에서 외부망을 받을 수 있다. 하지만 ElastiCache는 VPC 내부에서만 호출할 수 있다. 그 이유는 바로 Redis 자체의 보안성 때문… Linux 기반의 OS나 DB Client들은 공격 방어를 위해 여러 보안 장치들을 해두었지만 Redis는 그런 부분이 부실하다. 그래서 VPC 내부에서만 접속할 수 있게 설정해둔 것이다. 그렇다면 로컬에서 바로 Redis 서버에 접속하지 못하는가? 그것도 방법이 있다.

VPC 내부로 들어가기 - Bastion Host

Bastion Host[배스천 호스트] 를 사용하면 VPC 내부로 접속할 수 있다. Bastion Host는 쉽게 말해서 전달자의 역할이라고 보면 편하다. 로컬에서 VPC 내에 있는 EC2 서버로 접속하면, 해당 EC2 서버에서는 ElastiCache로 접근할 수 있다. 그래서 로컬 서버가 EC2로 Redis에서 어떤어떤 정보를 달라! 하면 EC2 서버는 Redis에 어떤어떤 정보가 있는지 찾아서 갖다준다고 생각하면 편하다. 이렇게 되면 캐시서버에 대한 직접접속을 막게 되어 보안성에서 이점을 가져갈 수 있다. 여기에서는 SSH 터널링이라는 기법이 함께 사용된다.

Primary와 Replica, Failover, 그리고 HA(High Availability)

Redis는 Primary Node와 Replica Node가 있다. 각각의 용도를 살펴보면… Primary는 대빵, Replica는 복제본이라고 보면 된다. Redis는 읽기에 특화되어있기 때문에 Replica Node 여러개를 만들어서 읽기전용으로 데이터를 읽을 수만 있게 하고, Primary Node는 읽고쓰기가 둘 다 가능하게 설정이 되어있다. 이렇게 되면 여러 이점이 생긴다.

일단 장애대응에 있어 엄청난 능력을 발휘한다. Redis는 인메모리 캐시 서버이기 때문에 장애가 발생하면 경우에 따라 메모리 안에 있는 데이터가 날아갈 수 있다. 그런데 여기서 Primary Node에 장애가 발생하면? 단순히 Replica Node들 중에 하나를 Primary Node로 바꿔버리면 끝이다. 그러면 자연스럽게 기존 Primary Node는 장애복구를 마친 뒤 Replica Node가 되는 것이다. 이렇게 되면 서비스 중단 없이 장애에 대응할 수 있게 된다. 이걸 고가용성(HA, High Availability)라고 부른다.

여기에 AWS는 멀티AZ(Availability Zone)을 이용할 수 있게 한다. AZ는 하나의 리전 내에 지리적으로 분리된 일종의 데이터센터라고 보면 되는데, 지진이나 정전 등의 자연재해가 발생하여 특정 AZ에 장애가 발생했다고 하더라도, 다른 AZ에 Replica가 있으니 그 Replica를 Primary로 승격시켜버리면 되는 것이다. 이렇게 하면 100%에 가까운 사실상 무중단 서비스를 이용할 수 있게 된다.

3. 그래서 Redis가 뭐하는거냐?

레디스는 Remote Dictionary Server의 약자로서, "키-값" 구조의 비정형 데이터를 저장하고 관리하기 위한 오픈 소스 기반의 비관계형 데이터베이스 관리 시스템이다. 2009년 살바토르 산필리포가 처음 개발했다. - 위키백과

Redis의 Data Type 🔗 (opens in a new tab)

  • Strings : 문자열을 저장
  • Lists
    • value에 리스트를 저장
    • lpush, lpop, rpush, rpop 같은 명령어를 이용해서 리스트를 조작하고, 스택이나 큐같은 자료구조도 구현할 수 있다
  • Sets
    • value를 set 형태로 저장
    • list는 중복이 되지만 set은 중복이 안됨
  • Sorted Sets
    • Sets와 유사하지만 score와 함께 저장되어 score를 기준으로 정렬됨
  • Hashes
    • key/value 목록을 값으로 가진다
  • Bitmaps
    • bit값을 저장해준다
    • 512MB 용량으로 2&32(42억)개의 bit값들을 저장할 수 있다

샤드와 노드

메모리를 캐시로 사용하기 때문에 단일 서버에 용량을 아주 크게 가져가기 힘들다. 그래서 용량을 수평적으로 확장할 때 ‘샤드'를 사용한다.

노드는 인스턴스와 유사한 개념으로 Primary/Replica 개념을 가진다.

4. Redis 기본 명령어들

CRUD

redis-cli
# set {key} {value}
set result 'success'
 
# mset {key} {value} {key} {value} ...
mset key_a val_a key_b val_b
 
# setex {key} {expire_seconds} {value}
setex minute 60 minute
redis-cli
# get {key}
get result
> "success"
 
# mget {key} {key} ...
mget key_a key_b
> 1) "val_a"
> 2) "val_b"
redis-cli
# del {key}
del result
 
# flushall (전체삭제)
flushall
redis-cli
# keys {key}
keys *
> 1) "key_a"
> 2) "key_b"
> 3) "minute"
redis-cli
# rename {기존key} {변경key}
rename key_a key_one

TTL

redis-cli
# ttl {key}
ttl minute
> (integer) 55

5. Redis로 세션 다루기

세션이 뭐지? 어디에 저장하지?

웹사이트에서 회원을 인증하는 방식은 크게 세션방식과 토큰방식이 있다. 세션은 로그인이 완료되면 서버와 브라우저에 각각 동일한 session_id를 두고, 브라우저에서 session_id를 서버에 보내면 서버는 회원임을 인증하고 session별로 저장해둔 값들을 불러와서 사용할 수 있다. 이에 반해 토큰은 인증만을 처리하고 서버에는 따로 데이터를 두지 않는 특징이 있다.

일반적으로 세션은 서버컴퓨터에 파일로 저장이 된다. 유저별로 세션파일이 생기고, 해당 세션파일로 유저를 관리하는 것이다. 하지만 서버가 여러대라면 서버 간에 세션이 공유되지 않는 문제점이 있다.

서버가 여러대라면?

서버가 여러대라면 보통 데이터베이스나 레디스같은 별도의 저장소에 세션을 저장하게 된다. 기본적으로 데이터베이스는 하드디스크나 SSD에 기록을 하는데 반해 레디스는 메모리에 저장하여 속도가 빠르고, key-value 형태로 데이터를 저장하는 세션의 특성상 NoSQL 방식이 성능상 이점을 가진다. 그리고 메모리 특성상 시스템 장애로 데이터가 날아가더라도 세션에 저장된 정보는 비교적 일회성으로 사용되는 경우가 많기 때문에 휘발에 대한 부담감도 적어서 Redis로 세션을 다루는 경우도 많다.

6. Redis Pub/Sub

publish는 발행하다, subscribe는 구독하다. 메세지를 발행하면 해당 채널을 구독중인 곳으로 메세지를 보낸다. 보통 서비스 내의 비즈니스 이벤트를 처리하는데 이런 방식이 사용된다. Message Queue라는 개념이 있는데, 레디스는 메세지큐 대용으로 적합하지는 않지만, 유사한 방식으로 활용된다고 보면 된다.

Subscribe

redis-cli
subscribe Channel

Publish

redis-cli
publish Channel "hello"