Redis 적용 (nodeJS, express)
Redis 적용 환경
꿀모 www.ggulmo.com 사이트를 개발하는 도중 메인페이지, 각 탭의 첫 페이지 등 사용자들이 많이 접근하는 화면에서 더 빠른 동작을 위해 Redis 적용을 고려하게 되었다.
현재 꿀모는 nodeJS(express) 와 mongoDB로 backend가 구성되어 있다.
MongoDB에 접근하는 수를 줄이고 redis에 접근하여 더 빠르게 데이터를 가져올 수 있도록 바꾸어 보려고 한다.
Redis란?
보통의 DB들은 데이터를 SSD나 disk에 저장해놓는다.
그러나 Redis는 데이터를 전부 memory에 올려놓고 가져다 사용한다. (In-Memory data structure store)
Memory에 접근하는 것이 disk에 접근하는 것보다 빠르게 때문에 빠른 속도로 접근이 필요한 데이터들을 redis를 통해 관리한다(cache 역할). 성능은 서버에 따라 다르지만 초당 2만~10만회 수행한다고 한다.
적용 예시
Key-Value
Redis는 key-value 방식으로 간단하게 관리할 수 있다.
redis set 메소드로 원하는 데이터를 원하는 key값에 매칭시킨다.
redis.set(“KEY”, “VAL”)
Redis get 메소드로 set해놓은 데이터를 가져올 수 있다.
redis.get(“KEY”)
nodeJS 기준 적용
다음은 nodeJS(express)에서 redis 사용에 대한 코드 예시이다.
- redis 설치
npm i redis - redis client 생성
- redis 사용 (get, set)
Data type
Redis는 기존 key-value 저장소보다 다양한 data type을 지원한다. Redis가 지원하는 data type은 다음과 같다.
- Strings
- Lists
- Sets
- Sorted Sets
- Hashes
- Bit arrays (Bitmaps)
- HyperLogLogs
- Streams
특징
- Redis는 Single thread로 동작한다.
- Redis 명령어들의 대부분은 시간복잡도가 O(1)이다.
- 시간복잡도가 O(1)이 아닌 명령어들도 있다.
Keys : 모든 key를 조회한다.
FLUSHALL, FLUSHDB : 데이터를 모두 삭제한다.
Delete Collections : Collection을 전부 삭제한다.
Get All Collections : Collection을 전부 조회한다. - Single thread이기 때문에 위와 같이 처리 시간이 긴 명령어가 들어오면 뒤에 명령어들은 대기 상태가 된다. 서버의 속도가 오히려 느려질 수 있기 때문에 가능한 사용하지 않는 것이 좋다.
Cache
Redis를 cache처럼 사용하려고 한다.
아래는 사용자가 데이터를 요청할 때의 프로세스이다.
- Redis에 해당 데이터가 있는지 확인한다.
- 있다면 Redis에서 받은 데이터를 돌려준다.
- Redis에 데이터가 없다면 mongoDB에 접근하여 필요한 데이터를 가져온다.
- 사용자에게 데이터를 돌려준다.
- Redis에 방금 받아온 데이터를 추가한다.
이렇게 Redis를 OS의 cache처럼 사용하려고 한다. 접근한 데이터들을 메모리에 올려놓고 빠르게 사용하고 접근이 자주 일어나지 않는 데이터는 디스크(DB)에서 찾는 형태이다. Redis의 용량(메모리)이 부족해지는 경우 LRU정책으로 오랫동안 접근되지 않은 데이터를 드랍할 것이다.
Worker
Refresh
위의 사용자가 데이터를 요청할 때의 프로세스 5번을 보면 Redis에 데이터를 추가한다. 하지만 꿀모 사이트의 특성상 데이터가 수시로 올라오고 데이터의 상태도 계속 변한다. 그렇기 때문에 Redis에 올라온 데이터도 update가 필요하다. 이를 위해 worker라는 프로세스를 만들었다.
동작 방식
worker는 새로운 값을 redis에 등록할 때마다 thread를 생성(fork)해서 해당 키 값에 매칭되는 데이터를 특정 주기로 refresh해준다. thread하나마다 redis의 key하나를 담당하는 것이다.
확장성
Redis는 Single thread로 동작하기 때문에 이런 방식으로 redis의 데이터를 관리하면 redis 원래의 빠른 동작을 활용할 수 있고 scalable하게 구현할 수 있다. Redis에 저장되는 key-value가 많아지면 worker의 수를 늘리면 된다. worker의 수를 늘리면서 성능 저하가 일어나지 않기 때문에 scalable하다.
구현 방법
이를 구현하기 위해 redis에 request_cache라는 이름의 key에 배열(queue)를 저장한다. Queue에는 새로 추가할 데이터에 대한 key string과 query를 넣어준다. worker는 redis의 request_cache를 계속 보고 있으면서 새로운 값들이 들어올 때마다 thread를 생성하고 redis에 해당 key string과 쿼리문의 결과를 저장하고 이후 주기적으로 refresh한다.
Future
현재는 redis를 자주 접근하는 데이터에만 적용했다. Cache로써의 역할만 부여했다.
하지만 앞으로 DB에 자주 접근해야 하는 경우에 활용할 수 있는 여러 사례가 있을 것 같다.
예를 들어 좋아요 처리, 출석 이벤트, 최근 검색 목록 표시 등 user define 한 데이터에도 Redis를 적용하면 좀 더 좋은 성능으로 구현할 수 있다.
해당 기능들의 구현에 Redis의 적용도 생각하면서 사이트를 개발해나가려고 한다!!