대규모 서비스를 운영하기 위해 데이터를 안전하고 빠르게 저장하고 불러오는 기술이 필요해진다.
이런 상황에서 Redis를 고려할 수 있다.
Redis는 시스템 메모리를 사용하는 key-value 데이터 스토어이다.
인 메모리 상태에서 데이터를 처리함으로써 흔히 사용하는 관계형 데이터베이스(RDS) 그리고 몽고 DB와 같은 문서형(Document) 데이터베이스 보다 빠르고 가볍게 동작한다.
Redis를 이용할 때 크게 2가지 방법을 사용한다.
로컬 환경에서 Redis를 호출한다.
AWS EC2를 예로들어, 인스턴스에 Redis를 설치해 인스턴스 메모리를 사용함으로써 Redis를 사용하는 방법이다.
인스턴스의 메모리 여유가 있다면 비용적으로도 사용성 측면에서도 뛰어나다.
클라우드 서비스를 사용해 외부 자원을 사용하는 방법이다.
레디스 랩(https://redislabs.com) 등의 서드파티 서비스를 상요해 Redis를 사용하면 통신하는 웹 서버가 아무리 많아도 하나의 프레임워크 바인딩을 사용할 수 있다.
이 경우 Redis는 여러 웹 서버들의 공유 메모리 역할을 감당할 수 있다.
Key-Value 스토어
Key-Value를 저장할 수 있는 스토리지를 지원한다.
컬렉션 지원
List, Set, Sorted Set, Hash 등의 자료구조를 지원한다.
Pub/Sub 지원
Publish/Subscribe 모델을 지원한다.
디스크 저장(Persistent Layer)
현재 메모리의 상태를 디스크로 저장할 수 있는 기능과 현재까지의 업데이트 내용을 로그로 저장할 수 있는 AOF(Append Only File) 기능이 있다.
복제(Replication)
다른 노드에서 해당 내용을 복제할 수 있는 Master/Slave 구조를 지원한다.
빠른속도
이상의 기능을 지원하면서 초당 100,000 QPS(Queries Per Second) 수준의 높은 성능을 지원한다.
ANSI C 로 작성
C 언어로 작성되어 Java와 같이 가상머신 위에서 동작하는 언어에서 발생하는 성능 문제에 대해 자유롭다.
다만, 곧바로 기계어로 동작하지 않고 어떤 가상 마선 위에서 인터프리터된 언어로 가동되는 경우에는 가비지 컬렉션(Garbage Collection) 동작에 따른 성능 문제가 발생할 수 밖에 없다.
Redis는 싱글 쓰레드이다. 메모리 파편화가 발생하기 쉽다. 메모리를 2배로 사용한다.
그래서 스냅샷을 뜰 때 자식 프로세스를 하나 만든 후 새로 변경된 메모리 페이지를 복사해서 사용한다.
Redis는 Copy-on-Write 방식을 사용한다.
보통 Redis를 사용할 때는 데이터 변경이 잦기 때문에 실제 메모리 크기만큼 자식 프로세스가 복사하게 된다.
이런 이유로 실제로 필요한 메모리 양보다 많은 메모리를 사용하게 된다.
Redis는 싱글 쓰레드이기 때문에 긴 transaction이 들어오면, 그 Tx를 처리하기 위해서 다른 request를 처리하지 못하는 현상이 발생한다.
예를 들어 Flushall이나 keys는 List 전체를 scan하는 구조인데, 100만개 처리시 1초, 1000만개에 10초, 1억개에 100초가 소요된다.
이를 예방하기 위해서 데이터를 전체 하나의 collection에 넣지 않고 여러 개의 collection에 나눠 처리하는 방안이 좋다고한다. 각 collection 당 보통 10,000개 정도의 데이터를 저장한다.
Redis는 한 번 생성한 키를 선택적으로 삭제하기 어렵다.
특별한 조치를 하지 않는다면 Redis의 키는 삭제가 아니라 보관되며, 서버를 종료했다 다시 켜도 상태가 유지된다.
Redis 키를 삭제하는 방법은 크게 3가지이다.
일괄 삭제
FLUSHDB 명령어를 통해 모든 키를 파괴한다. 복구가 불가능하며 보통 개발 수준에서 사용한다.
일정 시간 이후 삭제
각각의 Key를 저장할 때 셋에 저장해 특정 시간이나 조건에 따라 삭제하는 방법이다.
✅기간 만료 후 삭제
가장 많이 사용되는 방법이다. 키를 추적할 필요도 없고, 쉽게 관리할 수 있다.
이 방법을 사용할 때는 Key-Value 를 SET 커맨드로 저장해 EXPIRE 커맨드로 기간 만료시간을 정하는 방식이다.
또는 Redis 2.0.0 버전 이상을 사용할 대 SETEX 커맨드를 사용할 수 있다.
SETEX는 SET과 EXPIRE를 합친 느낌이다.
Redis는 운영중인 웹 서버에서 key-value 형태의 데이터 타입을 처리해야 하고, I/O가 빈번히 발생해 다른 저장 방식을 사용하면 효율이 떨어지는 경우에 사용한다.
I/O가 빈번한 데이터는 조회수와 같이 카운트 형태의 데이터일 수 있다.
유튜브의 경우 인기가 높은 채널의 신규 동영상은 짧은 시간안에 100만 조회수를 넘기는 일이 잦다.
이 때, 조회수에 해당하는 데이터를 RDS형태의 데이터에 저장해 I/O를 반복한다면 엄청나게 많은 자원이 사용될 것이다.
이럴 때 Redis를 사용해 데이터를 캐싱 처리하고, 일정 주기에 따라 RDS에 업데이트 한다면 RDS에 가해지는 부담을 크게 줄일 수 있을 것이다. 성능도 자연히 향상될 것이다.
이런 과정을 Redis만 사용해 처리하는 것은 어려운 일이다. 백엔드에서 연산처리를 해줘야 한다.
스케쥴러 코드를 만들어 일정 주기나 컨디션에 따라 Redis와 RDS간 데이터 업데이트를 해줘야 한다.
https://brunch.co.kr/@jehovah/20
youngerjesus님 velog
https://brunch.co.kr/@skykamja24/575
https://yjam.tistory.com/50