-
[TIL] 캐싱으로 조회수기능 개선하기TIL 2024. 11. 27. 14:57
캐싱으로 조회수기능 개선하기
기존 조회수기능 방식)
DB update 조회수+1
async increaseViewCount(reviewIdx: number): Promise<void> { await this.prismaService.reviewTb.update({ where: { idx: reviewIdx, }, data: { viewCount: { increment: 1, }, }, }); }
기존 조회수 기능의 문제점)
- 트래픽이 많아질수록 인덱싱된 데이터의 수정작업이 계속 이루어지게되면서 DB작업에 부담이 늘어난다.
- DB작업은 컴퓨터작업의 가장 느린부분으로 작업량이 늘어날때 병목현상이 일어나서 시스템 전체의 성능이 떨어질 수 있다.
- 그래서 불필요하게 DB에서 입출력작업이 많이 발생하지 않도록 해야한다.
캐싱기법 도입시의 장점)
- 캐싱기법은 조회수 증가작업을 일시적으로 메모리에 모아놨다가 한번에 할 수 있도록 해준다. 따라서 기존에 수시로 DB데이터 수정작업이 이루어지던 것을 한번의 메모리의 입출력작업으로 대체한다. 이처럼 주기적으로 캐시에서 DB로 데이터를 동기화해줌으로써 DB부하를 줄인다.
- 캐싱은 메모리 데이터를 저장함으로써 디스크의 I/O보다 훨씬 빠르게 동작한다.
하지만 캐싱을 통해 주기적으로 조회수를 업데이트하는 것만 반영한다면 실시간으로 조회수를 보여줄 수 없게된다.
이를 해결하기위해 조회수를 증가시키는 작업뿐만아니라 조회수를 표시할 때도 캐시를 이용해야한다.
캐싱기법 도입시의 단점과 보완)
- 캐시와 DB의 데이터 일관성을 유지하기 위해 동기화 전략이 필요하다
-> 캐시된 데이터를 주기적으로 DB에 반영했다.
캐싱을 통한 실시간 조회수 반영)
- 조회수 증가 시 : 조회수 증가를 캐시에 저장.
- 조회수 표시 시 : 조회수를 표시할 때도 캐시에서 가져와 실시간으로 보여준다.
캐싱이 적용된 조회수 기능 코드)
조회수 증가 메서드
//조회수 증가 메서드 async increaseViewCount(reviewIdx: number): Promise<void> { await this.redis.incr(`review:${reviewIdx}:viewCount`); }
조회수 불러오기 메서드
1.캐싱된 조회수 찾기
2.캐싱된 조회수가 없다면 DB에서 찾기
// 조회수 불러오기 메서드 async getViewCount(reviewIdx: number): Promise<number> { //메모리에서 조회수를 불러오기 let viewCount = parseInt( await this.redis.get(`review:${reviewIdx}:viewCount`), 10, ); //없다면 DB에서 조회수를 불러오기 if (!viewCount) { const review = await this.getReviewByIdx(reviewIdx); viewCount = review.viewCount; await this.redis.set(`review:${reviewIdx}:viewCount`, viewCount); } return viewCount; }
주기적으로 캐싱된 데이터 DB 동기화
1. 생성자내부에서 실행하여 객체 생성 즉시 주기적으로 동기화 진행
2.동기화한뒤 캐싱된 데이터 삭제
//주기적으로 캐싱된 조회수 DB에 동기화 //생성자 내부에서 실행하여 객체생성 즉시 주기적으로 동기화 setInterval( async () => { const keys = await this.redis.keys(`review:*:viewCount`); for (const key of keys) { const reviewIdx = key.split(':')[1]; const viewCount = await this.redis.get(key); await this.prismaService.reviewTb.update({ where: { idx: parseInt(reviewIdx, 10), }, data: { viewCount: parseInt(viewCount, 10), }, }); } }, 10 * 60 * 1000, );
'TIL' 카테고리의 다른 글
[TIL] Github git clone VS git fork 차이점 알아보기 (0) 2024.12.02 [TIL] SSE로 알람기능 구현하기 (Polling / Long Polling / Web Socket / SSE (Server Sent Event)) (0) 2024.11.18 [github-actions] 프라이빗 레포지토리 CI/CD 자동배포 설정하기 (0) 2024.11.13 [TIL] Refresh Token 을 사용하는 이유와 구현 방식 (0) 2024.10.14 [TIL] Error - git 파일명 대소문자 구분 (0) 2024.10.13