2025. 4. 6. 23:28ㆍ개발
좋아요 수, 유저-좋아요, 인기 게시글 목록을 저장할 자료구조
레디스의 공식문서를 보았을 때 다음과 같은 방식을 고안했다.
방법 1. 좋아요 수 카운팅을 HashSet으로 관리, 랭킹 목록은 List로 저장. 일정 주기마다 디비에서 랭킹 갱신
이 방법은 좋아요 증가가 빠르다. 즉 M개의 요청에 대해 O(1).
단점은 랭킹 주기가 일정 주기에 의존한다는 것.
방법 2. 좋아요 수를 SortedSet으로 저장하여 인덱스처럼 사용하는 것이다.(인기 게시글 목록은 hash로 저장) 물론 갑작스럽게 인기가 상승한 비 인기 게시글 까지의 고려를 위해 일정 주기로 디비로부터 갱신은 불가피하다.
이 방법은 실시간 정렬이 가능하다는 것이다. 단 고정된 인기 게시글 목록 내부에서.
단점은 조회시 추가적인 redis 호출이 필요하다는 것인데(1번은 인덱스 요청, 2번은 인덱스를 통한 인기 게시글 목록 요청) 이는 Lua 스크립팅으로 해결이 가능해 보인다.
또한 M개의 요청에 대해 O(MlogN)의 비용이 든다. 하지만 이 api에서 N은 10이다.
그래도 정확한 실시간 갱신에 대한 비용에 대해 따져보기 위해 redis에서 sorted set을 어떻게 구현했는지 알아봤다.
SortedSet은 어떻게 구현이 되어있나?
skip list + hashmap의 구조다.
skip list로 key와, 점수를 저장해 정렬을 유지하고 획득한 key로 hashmap에서 value에 접근한다.
skip-list는 삭제,삽입시 포인터들을 갱신해서 그 오버헤드가 예상된다.
=> **SortedSet은 크기가 작을 때, list-pack으로 구현됨
위 두개의 방법으로 구현을 하였을 때, 가정하였던 '1000명 동시 요청'상황 으로 테스트를 해보았다.
(단 gcp credit이 만료돼서 전부 로컬에서 했다..)
<결과>
차이가 없다. => 목표로한 상황에서 sorted set으로 구현함으로 써 생기는 성능 저하가 없다.
만약에 이 레디스 서버 수를 증설한다면?
레디스 서버가 2개라고 하자. 10개의 서버중 5개를 1번 레디스, 나머지 5개를 2번 레디스에 요청을 보낸다고 할때, 방법2 를 선택한다면 각 레디스 서버가 유지하고 있는 좋아요 수는 다르다. 결국 어떤 서버에 요청하느냐에 따라 사용자에게 반환하는 랭킹이 달라질 것이다. 이것은 사용자에게 매우 안좋은 경험을 유발한다.
다른 서비스들은 어떻게 할까
과거 네이버의 실시간 인기 검색어를 볼때 주기적으로 순위를 업데이트한다. 이때 사용자들 경험을 보아서는 정말 리얼타임 랭킹 변화가 유의미 하지는 않은 것 같다.
또한 에브리타임에서 핫 게시글에 좋아요를 누르고 바로 전체 핫 게시글 목록에서 보이는 좋아요 수가 업데이트 되지 않는다. 직접 시간을 재보았을 때, 3분정도 단위로 업데이트가 된다. 사용자 수를 보았을 때, 대학교 전체 재학생은 2만명 정도. 그렇다면 동시간대 요구되는 TPS는 우리 서비스와 동일하지 않을까? 라는 추측을 할 수 있다. 사용자들 반응을 보았을 때(아예 모르는거 같기도 하다) 사용자들 경험을 보아서는 정말 리얼타임 랭킹 변화가 유의미 하지는 않은 것 같다.
따라서 위의 근거를 바탕으로 방법1을 선택했다.
다음글
https://loftspace.tistory.com/50
인기게시글 도입을 위한 과정 - 더 추가적인 고민
이전 글. https://loftspace.tistory.com/46 인기 게시글 도입을 위한 과정 - 자료구조의 선택 그리고 추가적인 고민좋아요 수, 유저-좋아요, 인기 게시글 목록을 저장할 자료구조레디스의 공식문서를 보
loftspace.tistory.com
Reference :
'개발' 카테고리의 다른 글
인기게시글 도입을 위한 과정 - 추가적인 고민 (0) | 2025.04.25 |
---|---|
트랜잭션 데드락 - 고민 (0) | 2025.04.06 |
트랜잭션 데드락 - 외래키 제약조건 (0) | 2025.04.06 |
인기 게시글 도입을 위한 과정 - 캐싱과 쓰기전략 (1) | 2025.04.06 |
인기 게시글 도입을 위한 과정 - 기획 (0) | 2025.02.17 |