개요
티스토리 블로그관리 창에 들어가면 날짜 별 조회수를 나타내주는 아래와 같은 사진이 보입니다.
현재 진행중인 동영상 조회 플랫폼 Inugram에도 이 기능을 한번 적용해보겠습니다.
설계
영상 조회수 기능을 설계하기 전, 스스로 세가지 조건을 고려하며 설계하였습니다.
1. 다중 사용자 조회 시 lost update 문제가 발생하면 안된다.
2. 많은 사용자 트래픽을 수용할 수 있어야 한다.
3. 사용자가 매 일자마다 조회수가 얼마나 집계되었는지 확인할 수 있어야한다.
일단 첫 번째 문제는 두 가지 방식으로 해결할 수 있습니다.
1. RDB에 락을 걸어서 lost update를 방지한다.
2. 조회 수 저장소로 Redis를 사용해서 INCR 명령어로 원자적 연산을 수행한다.
만약 첫 번째 방법을 사용하게되면 무거운 Disk I/O 작업을 여러번 수행하기 때문에 많은 사용자 트래픽을 수용할 수 없을 것입니다.
그래서 두가지 조건을 모두 만족시키기 위해 조회 수 저장소로 Redis를 사용하기로 결정했습니다.
하지만 Redis를 사용했을 때도 고려할 점이 있습니다.
만약 모든 조회수 정보를 Redis에 저장한다면 값 비싼 메모리를 상당히 많이 사용해야하는 문제가 생길 수 있습니다.
그래서 이를 방지하기 위해 Redis의 데이터를 매일 한번씩 RDB에 반영하고, 초기화시켜 메모리를 효율적으로 사용해보겠습니다.
조회수 조회 기능 구현
조회 기능은 위와 같이 동작합니다.
일단 Redis에 저장된 당일 조회 수를 가져옵니다.
이후, 영상이 게시된 시점부터 전날까지 조회된 조회 수를 가져오는데요, 이 때 Redis에서 먼저 데이터를 가져오려고 시도하고 cache miss가 발생했을 경우, RDB에서 해당 데이터를 가져온 뒤 Redis에 반영해줍니다.
이렇게하면 이후 조회되는 데이터에 대해서는 cache hit가 발생하여 좀 더 빠른 데이터 엑세스가 가능해집니다.
이후, 이전 조회수와 당일 조회수를 합쳐서 반환합니다.
이를 코드로 나타내면 아래와 같습니다.
조회수 상승 기능 구현
조회수 상승 기능은 간단합니다.
현재 날짜를 기준으로 key 값을 생성하고, 해당 키값에 +1을 해주면 됩니다.
여기서 주의할 점은 increment를 사용하는 것인데요.
key값을 조회하고 update를 하게되면 lost update 문제가 발생할 수 있기 때문에 redis에서 지원하는 원자적 연산인 INCR 명령어를 사용하기 위해 increment를 사용해서 값을 증가시켜야 합니다.
이를 코드로 나타내면 아래와 같습니다.
날짜별 조회수 분석 기능 구현
날짜별 조회수 분석 기능을 위해 아래 플로우를 설계하였습니다.
코드를 보면서 설명드리겠습니다.
우선, 매일 오전 두시 스케쥴러가 performTask 메서드를 실행하도록 설정했습니다.
performTask에서는 당일 조회된 데이터 리스트를 기반으로, VideoViewDetailEntity를 생성합니다.
VideoViewDetailEntity에서는 조회 수, 날짜, videoView 엔티티의 Id 값을 가지고 있습니다.
이를 기반으로 아래 사진과 같이 날짜별 조회수를 확인할 수 있는 것입니다.
이후 데이터 리스트를 saveAll 메서드를 이용해서 한번의 DB 커넥션으로 저장시킵니다.
그 다음 Redis에서 당일 조회된 데이터들을 모두 지웁니다.
이를 통해 Redis에서 모든 조회 데이터를 가지고 있지 않아서 메모리를 효율적으로 사용할 수 있습니다.
https://github.com/elyudwo/inugram
References
https://redis.io/docs/latest/commands/incr/
https://stackoverflow.com/questions/27521672/how-autowired-redistemplatestring-long
'개발 > SpringBoot' 카테고리의 다른 글
Spring MVC, Spring Webflux SSE 성능 비교 (0) | 2024.12.17 |
---|---|
Redis + Spring AOP를 활용한 Rate Limiter 기능 구현 (1) | 2024.11.16 |
S3 presigned Url 적용을 통한 영상 업로드 성능 향상 (0) | 2024.06.19 |
SpringDoc Swagger Https 설정법 (0) | 2024.04.11 |
네이티브 쿼리문 + @SqlResultSetmapping 을 이용한 조회 (0) | 2024.03.02 |