• 티스토리 홈
starryeye
  • 프로필사진
    starryeye
    • 분류 전체보기 (189)
      • C++ (17)
      • Java (24)
      • OOP (5)
      • Spring Reactive Stack (12)
        • Reactive Streams (3)
        • Netty (4)
        • Reactor (1)
        • Webflux (3)
        • DB, Cache 연동 (1)
      • Spring (90)
        • Core (17)
        • MVC (33)
        • Client (2)
        • Security (4)
        • DB, Cache 연동 (33)
      • DataBase (12)
        • RDBMS (2)
        • NoSQL (10)
      • Message Broker (6)
      • Web (4)
      • Network (4)
      • 대규모 시스템 설계 (15)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
      등록된 댓글이 없습니다.
    • 최근 공지
        등록된 공지가 없습니다.
      # Home
      # 공지사항
      #
      # 태그
      # 검색결과
      # 방명록
      • 시스템 설계 고민 2
        2023년 06월 09일
        • starryeye
        • 작성자
        • 2023.06.09.:59
        반응형

        가장 간단하게 구현한 시스템 부터 대규모 트래픽을 감당할 수 있을 정도의 시스템 까지
        생각하면서..
        시스템 설계 방법을 나열해보겠다..
        (아래 내용은 트랜잭션 격리 수준에 따라 내용이 좀 달라질 수 있다.)
        (틀린 점이 있을 수 있다.. 있으면 댓글 부탁드립니다.)
         
        기술 스택 : Spring, JPA, MySQL
         

        요구사항

        타임라인 기능 설계에 대해 고민해보자..
        타임라인 기능이란..
        내가 어떤 게시글을 작성하면..
        나를 팔로우하는 사람들은 내 게시글을
        각자의 타임라인 페이지(보통 home 페이지이다.)에서 볼 수 있는...
        기능이다. 
         
         
        각 방법에서 쓰기 관점과 조회 관점으로 나눠서 설명하겠다.
        A 사용자가 B 사용자를 팔로우 하였고,
        B 사용자가 게시글을 쓰는 상황이라 생각하자.
         
         

        첫번째 방법

        가장 간단하게 생각할 수 있는 설계 방법이다.

        post Table 을 위와 같이 설계한다.
         

        follow Table 은 위와 같이 설계한다.
         

        시스템은 위와 같다.
         

        쓰기 관점

        자 이제..
        B 사용자가 게시물을 작성하면
        post Table 에 row 가 하나 추가될 것이다.
         

        조회 관점

        문제는 조회 관점이다.
        A 가 타임라인 페이지를 진입 하는 순간..
        다음과 같은 과정이 일어난다.
         
        1. 우선 A 가 팔로우 하는 모든 member_id 를 follow Table 에서 조회 한다.
        2. 조회한 follow list 를 post Table 로 가서 적재된 게시물을 싹 가져와야 한다.
         
        참고
        원래 정렬도 해야하겠지만, 주제와 상관 없어서 생략한다.
        조인을 하건 쿼리 두번을 하건 주제와 상관 없어서 생략한다.
         
        즉, user Table(그림엔 없음) 과 follow Table 이 일대다 관계이고,
        follow Table 과 post Table 이 일대다 연관관계를 형성하고 있어서
        조회 시점에 큰 부하가 존재하는 것이다. (fan-out 문제)
        -> A 가 팔로우 한 사람이 엄청 많다고 생각해보자.. 
         
         
        첫번째 방법의 문제점은..
        보통 sns 는 게시글을 작성하는 것보다 게시글을 조회하는 상황이 훨씬 많다.
        보통 조회와 쓰기는 서로의 성능을 희생시키면 본인의 성능이 올라가는 상황이 많다. (Trade-off)
        두번째 방법에서 알아보자..
         
         

        두번째 방법

        조회 관점에서 일대다 연관관계를 없애보자..
         

        위와 같이 timeline Table 을 추가하였다.
         

        쓰기 관점

        B 사용자가 게시물을 쓰면.. 다음 과정을 따른다.
         
        1. post Table 에 row 하나를 저장
        2. follow Table 에서 나(B)를 팔로우하는 사용자(A) 들을 리스트로 조회한다.
        3. 나를 팔로우하는 사용자 리스트를  member_id 로 하여 timeline Table 에 하나씩 적재한다.
         
        첫번째 방법과 비교하여
        2번 과정이 조회에서 쓰기로 넘어왔고,
        쓰기 성능에 부하가 생기게 되었다.
        또한, timeline 이라는 Table 이 추가 되어 대용량 데이터 고민도 필요하게 되었다.
        -> 실제 Twitter 에선 Redis 로 해결하며 적절한 TTL 을 정해둔 것 같다.
         

        조회 관점

        조회 관점에서는..
         
        A 사용자가 타임라인 페이지에 들어가면..
        다음 과정을 따른다.
         
        1. timeline Table 에서 A 의 member_id 로 적재된, 게시물 post_id 를 리스트로 조회한다.
        2. post_id 리스트로 post Table 에 가서 게시물을 조회한다.
         
        첫번째 방법과 비교하여..
        조회 관점의 부하가 많이 준 것을 생각해 볼 수 있다.
        특히, 2번 로직은 일대일 매핑으로 이루어졌으며,
        팔로우 관련 fan-out 문제가 타임라인 조회에서 게시물 쓰기로 넘어갔다.
         
        하지만, 데이터 정합성(일관성) 문제가 생길 수 있다.
        첫번째 방법에서 테이블이 추가되었고 그 데이터는 모두 다른 테이블에서 복제한 값이다.
         
         
        정리 (시간복잡도, logN 은 생략하였다.)

         게시물 쓰기타임라인 조회
        첫번째 방법(fan out on read, pull model)O(1)O({내가 팔로우한 수} * {게시글 수})
        두번째 방법(fan out on write, push model)O({나를 팔로우한 수})O({게시글 수})

        -> 성능에 가장 영향을 많이 미치는 요소가 팔로우 수이고,
        게시글 수는 캐시 외에 어찌할 방법이 없어보인다. (접근을 해야 보여주니..)
         
        참고>
        twitter 는 push model, facebook 은 pull model 을 따른다고 한다..
         
         

        세번째 방법

        두번째 방법에서 게시물 쓰기시..
        나를 팔로우한 수만큼 timeline Table 에 쓰기 연산을 하는데..
        이 로직은 굳이.. 게시물 쓰기 시점에 완료할 필요는 없다.
        특히, 엄청난 팔로워를 보유한 연예인들이 게시물 하나 쓰면 대기시간이 엄청나게 오래 걸리니까..
        비동기로 빼도 된다.
        -> 그러면 첫번째 방법처럼 Post Table 에 row 하나만 추가하면 되는 수준의 시간복잡도를 기대할 수 있다.
         
        그러나..
        두번째 방법보다 더욱 데이터 일관성을 깊게 생각해야한다.
        중복데이터를 비동기로 뺀 덕분에 데이터 일관성은 더 고민해봐야 한다.
        -> 시스템 복잡도가 높다..

        위 사진은 Twitter 의 System Design 이다.
        쓰기 시점에 Tweet(게시물) 은 DB 로 적재하고
        팔로워에 해당 게시물을 알리는 로직은 비동기로 빠져있는 것을 볼 수 있다.
        조회 시점에도 Redis 를 이용하여 두번째 방법보다 빠르게 조회 할 수 있도록 한 것을 볼 수 있다.
         
         
        참고>
        아래 링크를 보면.. twitter 의 시스템을 설명해준다.
        https://www.youtube.com/watch?v=KmAyPUv9gOY
         
         
         

        반응형

        '대규모 시스템 설계' 카테고리의 다른 글

        Layered architecture faults and improvement  (0) 2023.06.22
        시스템 설계 고민 1  (0) 2023.06.08
        Event-Driven 아키텍처 와 Pub/Sub 모델  (0) 2023.06.03
        Hexagonal Architecture 정리  (0) 2023.05.15
        CQRS Pattern  (0) 2023.02.15
        다음글
        다음 글이 없습니다.
        이전글
        이전 글이 없습니다.
        댓글
      조회된 결과가 없습니다.
      스킨 업데이트 안내
      현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
      ("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
      목차
      표시할 목차가 없습니다.
        • 안녕하세요
        • 감사해요
        • 잘있어요

        티스토리툴바