캐시로써의 레디스

1. Look Aside (= Lazy Loading)

이름에서 알 수 있듯이 이 구조는 캐시를 옆에 두고 필요할 때만 데이터를 캐시에 로드하는 캐싱 전략입니다. 캐시는 데이터베이스와 어플리케이션 사이에 위치하여 단순 key-value 형태를 저장합니다. 어플리케이션에서 데이터를 가져올 때 레디스에 항상 먼저 요청하고, 데이터가 캐시에 있을 때에는 레디스에서 데이터를 반환합니다. 데이터가 캐시에 없을 경우 어플리케이션에서 데이터베이스에 데이터를 요청하고, 어플리케이션은 이 데이터를 다시 레디스에 저장합니다. 아래 그림은 이 프로세스를 나타내고 있습니다.

위 구조를 사용하면 실제로 사용되는 데이터만 캐시할 수 있고, 레디스의 장애가 어플리케이션에 치명적인 영향을 주지 않는다는 장점을 가지고 있습니다.하지만 캐시에 없는 데이터를 쿼리할 때 더 오랜 시간이 걸린다는 단점과 함께, 캐시가 최신 데이터를 가지고 있다는 것을 보장하지 못하는 단점이 있습니다. 캐시에 해당 key 값이 존재하지 않을 때만 캐시에 대한 업데이트가 일어나기 때문에 데이터베이스에서 데이터가 변경될 때에는 해당 값을 캐시가 알지 못하기 때문입니다.

 

2. Write-Through

Write-Through 구조는 데이터베이스에 데이터를 작성할 때마다 캐시에 데이터를 추가하거나 업데이트합니다. 이로 인해 캐시의 데이터는 항상 최신 상태로 유지할 수 있지만, 데이터 입력 시 두번의 과정을 거쳐야 하기 때문에 지연 시간이 증가한다는 단점이 존재합니다. 또한 사용되지 않을 수도 있는 데이터도 일단 캐시에 저장하기 떄문에 리소스 낭비가 발생합니다. 이를 해결하기 위해 데이터 입력시 TTL을 꼭 사용하여 사용되지 않는 데이터를 삭제하는 것을 권장합니다.

Redis의 활용사례

1. 좋아요 처리하기

가장 중요한 것은 한 사용자가 하나의 댓글에 한번만 좋아요 를 할 수 있도록 제한하는 것입니다. RDBMS에서는 유니크 조건을 생성해서 처리할 수 있습니다. 하지만 만약 많은 입력이 발생하는 환경에서 RDBMS을 이용한다면 insert와 update에 의한 성능 저하가 필연적으로 발생하게 됩니다

 

레디스의 set을 이용하면 이 기능을 간단하게 구현할 수 있으며, 빠른 시간 안에 처리할 수 있습니다. set은 순서가 없고, 중복을 허용하지 않는 집합입니다. 댓글의 번호를 사용해서 key를 생성하고, 해당 댓글에 좋아요를 누른 사용자의 ID를 아이템으로 추가하면 동일한 ID값을 저장할 수 없으므로 한 명의 사용자는 하나의 댓글에 한번만 좋아요를 누를 수 있게 됩니다.

 

2. 게임 서비스 일일 순방문자수 구하기

순 방문자수(UV)는 서비스에 사용자가 하루에 여러번 방문했다 하더라도 한번만 카운팅되는 값입니다. 즉 중복 방문을 제거한 방문자의 지표 라고 생각할 수 있습니다. 많은 서비스에서 이 수치를 이용해 사용자의 동향을 파악하고, 마케팅을 위한 자료로 활용하기도 합니다.

 

실제 서비스에서는 이를 구하기 위해서 대표적으로 세 가지 방법을 사용합니다. 첫번째로 액세스 로그(access log)를 분석하는 방법, 두번째로 외부 서비스(ex. Google Analytics)의 도움을 받는 방법, 세번째로는 접속 정보를 로그파일로 작성하여 배치 프로그램으로 돌리는 방법입니다. 이 세 가지 방법 중 GA를 제외하고는 정보를 실시간으로 조회할 수 없습니다.

 

그렇다면 이제 레디스의 비트 연산을 활용하여 간단하게 실시간 순 방문자를 저장하고 조회하는 방법을 알아보겠습니다. 게임의 유저는 천만명이라 가정하고, 일일 방문자 횟수를 집계하며 이 값은 0시를 기준으로 초기화됩니다.

 

사용자 ID는 0부터 순차적으로 증가된다고 가정하고, string의 각 bit를 하나의 사용자로 생각할 수 있습니다. 사용자가 서비스에 방문할 때 사용자 ID에 해당하는 bit를 1로 설정합니다. 1개의 bit가 1명을 의미하므로, 천만명의 유저는 천만개의 bit로 표현할 수 있고, 이는 곧 1.2MB정도의 크기입니다. 레디스 string의 최대 길이는 512MB이므로 천만명의 사용자를 나타내는건 충분합니다.

 

3. 최근 검색 목록 표시하기

이 기능을 관계형 데이터베이스를 이용해 구현하려면 아래와 비슷한 쿼리문이 필요합니다.

select * from KEYWORD where ID = 123 order by reg_date desc limit 5;

이 쿼리는 사용자가 최근에 검색했던 테이블에서 최근 5개의 데이터를 조회합니다. 하지만 이렇게 RDBMS의 테이블을 이용해서 데이터를 저장한다면 중복 제거도 해야하고, 멤버별로 저장된 데이터의 개수를 확인하고, 오래된 검색어는 삭제하는 작업까지 이루어져야 합니다.

 

따라서 애초에 중복을 허용하지 않고, 정렬되어 저장되는 레디스의 sorted set을 사용하면 간단하게 구현할 수 있습니다. sorted set은 가중치를 기준으로 오름차순으로 정렬되기 때문에, 가중치로 시간을 사용한다면 이 값이 가장 큰, 나중에 입력된 아이템이 맨 마지막 인덱스에 저장됩니다.

 

Redis의 Node 형태

https://meetup.toast.com/posts/227 참조!!

 


참고 자료 : 

https://meetup.toast.com/posts/225

https://meetup.toast.com/posts/226

https://meetup.toast.com/posts/227

'개발합시다. > BackEnd 공부' 카테고리의 다른 글

Spring Boot 실습기록 2  (0) 2021.12.08
Django의 request & Http  (0) 2021.12.08
Spring Boot 실습 기록 1  (0) 2021.12.07
Redis의 모든 것  (0) 2021.12.07
mongoDB의 모든 것  (0) 2021.12.07

+ Recent posts