ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2024.06.03 Design a Real-Time Leaderboard system
    TIL 2024. 6. 3. 22:45

     

    Design a Real-Time Leaderboard system for millions of users

     

    Design a Real-Time Leaderboard system for millions of users

    Unpacking Challenges, Assumptions, and the Scope of Real-Time Leaderboard Design

    medium.com

     

    사용자가 많고 쌓이는 데이터가 많을 때 rank를 뽑는 방법에 관한 글이다.

    RDB를 사용해 각종 정보를 저장할 때 rank나 limit를 통해 DB에서 데이터를 뽑을 수 있다.

    RDB는 관계형 데이터를 저장하기 적합하며 ACID 특성으로 트랜잭션 작업의 무결성을 지킬 수 있는 장점이 있다.

     

    평균 유저 기반으로 시간당 리퀘스트를 계산해보아야 한다. 글의 예시로는 1150 RPS이다.

    매번 풀스캔이 이뤄져야 하는 rank 작업은 많은 양의 데이터에서는 느리게 동작합니다.

     

    여기서는 해결방법으로 redis SortedSet을 사용합니다. 

    SortedSet에 점수를 넣고 정렬된 정보를 뽑는 것이다.

     

    액션 발생 시 직접 db나 redis에 넣지 않고 kafka를 통해 넣는다. 

    kafka를 사용하면 각 db에 데이터가 저장되는지를 기다릴 필요가 없어지는 장점이 있다.

     

    캐시

    요구사항으로 실시간 리더보드가 업데이트되길 바라지만 1150 RPS이라서 오히려 사용자에게 안 좋은 경험을 줄 수 있다.

    캐싱을 하면 실용적이며 유저에게도 좋은 경험을 줄 수 있다.

    또한 redis 캐시를 사용해서 범위검색 시간복잡도는 O(log(N) + M)이므로 매번 조회 시 o(1)보다는 성능이 떨어진다.

    캐시는 o(1)으로 유지하면 더 빠른 성능을 보장할 수 있다.

     

    구현방법으로는..

    레디스가 이벤트를 받아서 업데이트되면 다른 redis에 시간 저장과 리더보드 변경용 토픽에 변경된 시각 메시지를 보낸다.

    이후 메시지를 소비할 때 redis 리더보드 업데이트 시각과 비교를 하고 500ms 미만이라면 업데이트하지 않는다. 넘으면 업데이트하고.

    상위 10명을 받아서 효과적으로 캐시하고 조회 o(1)을 유지한다는 것이다.

    매번 redis에서 10명을 뽑지 않고.

    이후 10명 뽑은 것을 리더보드 kafka에 메시지를 발행한다.

     

    특정 주기마다 업데이트하는 방법과 다른 점은 사용자 이벤트가 있어야지 redis를 조회해 캐시 한다는 것이다.

    새벽같이 사용자가 적다면 동작하지 않고 사용자가 많은 일과시간에는 캐싱이 되는 것이다.

     

    프로토콜

    매번 커넥션을 맺고 끊는 http보다 websocket을 통해 정보 받는 것을 유지하는 것이 낫다고 판단하다.

    여기서는 STOMP를 사용했다.

    pub/sub구조로 관리되는 거 같다. kafka로 데이터 변경 이벤트를 받으면 연결된 socket으로 데이터를 뿌리는 거 같다.

    websocket 말고 polling으로도 할 수 있는데 위에서 redis에 말한 방식과 동일하게 서버로드 증가와 대기시간 증가라는 단점이 생긴다.

     

     

    재밌는 구조이다. 캐시 change 시에

    다시 보면.

    1. 사용자의 액션 발생

    2. game서비스가 이벤트를 받아서 db저장을 위한 kafka 이벤트 발행

    3. rdb에 저장

    4. reids에 저장

    5. redis에 저장하면서 데이터 변경 kafka 이벤트 발행

    6. redis변경 캐시 서비스는 해당 이벤트를 읽고 기존 업데이트 내역과의 시간차를 계산해 500ms 이상 차이가 난다면 캐시를 업데이트함

    7. 업데이트를 했다면 리더보드 토픽에 이벤트를 발행한다.

    8. 리더보드 토픽을 구독하는 서비스는 웹소켓 컨슈머들에게 이벤트를 발행한다. 

    9. 클라이언트들은 연결해서 데이터를 가져간다.

     

    총 kafka토픽이 3개 사용된다. db저장용. 캐시 flush용, websocket 호출용.

    재밌는 구조인데 이로서 얻을 수 있는 장점이 클까. 사용자가 많은 서비스의 경우는 효과적이겠다. 

     

    댓글

Designed by Tistory.