Post

[Book - 가상 면접 사례로 배우는 대규모 시스템 설계 기초] 11. 뉴스 피드 시스템 설계

1단계. 문제 이해 및 설계 범위 확정

1
2
3
4
5
6
7
8
9
질문
* 모바일? 웹?
* 중요 기능은?
* 뉴스 피드에서의 스토리 순서 기준은?
    * 최신? topic score?
    * 가까운 친구?
* 한 명의 유저가 가질 수 있는 최대 친구 수는?
* 트래픽 규모는?
* 피드에 이미지나 비디오 스토리도 올라올 수 있는지?

2단계. 개략적 설계안 제시 및 동의 구하기

두 가지 설계안을 살펴 보자.

  1. 피드 발행(feed publishing) ```
    • 사용자가 스토리를 포스팅하면 해당 데이터를 캐시와 데이터베이스에 기록한다.
    • 새 포스팅은 친구의 뉴스 피드에도 전송된다. ```
  2. 뉴스 피드 생성(news feed building) ```
    • 지면 관계상 뉴스 피드는 모든 친구의 포스팅을 시간 흐름 역순으로 모아서 만든다고 가정한다. ```

뉴스 피드 API

  • 상태 정보 업데이트
  • 뉴스 피드 조회
  • 친구 추가

1. 개략적 설계안: 피드 발행

피드 발행

  • 포스팅 저장 서비스(post service)
    • 새 포스팅을 데이터베이스와 캐시에 저장
  • 포스팅 전송 서비스(fanout service)
    • 새 포스팅을 친구의 뉴스 피드에 push
    • 뉴스 피드 데이터는 캐시에 보관하여 빠른 조회
  • 알림 서비스(notification service)
    • 친구들에게 새 포스팅이 올라왔음을 알리거나, 푸시 알림을 보내는 역할을 담당

2. 개략적 설계안: 피드 생성

피드 생성

  • 뉴스 피드 서비스(news feed service)
    • 캐시에서 뉴스 피드를 가져오는 서비스
  • 뉴스 피드 캐시(new feed cache)
    • 뉴스 피드를 렌더링할 때 필요한 피드 ID를 보관

3단계. 상세 설계

뉴스 피드 발행과 생성 부분의 설계를 보다 상세히 살펴보자.

피드 발행 흐름 상세 설계

피드 발행 흐름 상세 설계

  • 웹서버
    • 인증, 처리율 제한
    • 스팸을 막고, 유해한 컨텐츠가 자주 올라오는 것을 방지하기 위해서 특정 기간 동안 한 사용자가 올릴 수 있는 포스팅의 수에 제한을 두어야 한다.
  • 포스팅 전송(팬아웃) 서비스
    • fanout은 어떤 사용자의 새 포스팅을 그 사용자와 친구 관계에 있는 모든 사용자에게 전달하는 과정
    • 모델 종류
      1. 쓰기 시점: fanout-on-write하는 모델(push model)
      2. 읽기 시점: fanout-on-read하는 모델(pull model)

쓰기 시점에 팬아웃하는 모델

새로운 포스팅을 기록하는 시점에 뉴스 피드를 갱신하게 된다.
즉, 포스팅이 완료되면 바로 해당 사용자의 캐시에 해당 포스팅을 기록한다.

  • 장점
    • 뉴스 피드 실시간 갱신 -> 친구 목록에 있는 사용자에게 즉시 전송
    • 새 포스팅이 기록되는 순간 - 뉴스 피드가 이미 갱신됨(pre-computed) -> 뉴스 피드를 읽는 데 드는 시간 단축
  • 단점
    • 핫키(hotkey) 이슈
      • 친구가 많은 사용자의 경우 -> 친구 목록을 가져오고 그 목록에 있는 사용자 모두의 뉴스 피드를 갱신 -> 많은 시간 소요
    • 서비스를 자주 이용하지 않는 사용자의 피드까지 갱신 -> 컴퓨팅 자원 낭비

읽기 시점에 팬아웃하는 모델

피드를 읽어야 하는 시점에 뉴스 피드를 갱신한다. 따라서 요청 기반(on-demand) 모델이다.
즉, 사용자가 본인 홈페이지나 타임 라인을 로딩하는 시점에 새로운 포스트를 조회하게 된다.

  • 장점
    • 휴먼계정 또는 로그인을 거의 하지 않는 사용자의 경우 -> 로그인하기까지는 어떤 컴퓨팅 자원도 소모X
    • 데이터를 친구 각각에 푸시하는 작업X -> 핫키 이슈X
  • 단점
    • 뉴스 피드를 읽는 데 많은 시간 소요

쓰기 시점에 팬아웃하는 push모델과 읽기 시점에 팬아웃하는 pull모델을 결합하여 장점은 취하고, 단점은 버리는 전략을 설계해보자.

  • 뉴스 피드 빠른 조회
    • push 모델
      • 대부분의 사용자
    • pull 모델
      • 친구나 follower가 아주 많은 경우
      • 시스템 과부하 방지
  • 핫키 이슈 완화
    • 안정 해시를 통해 요청과 데이터를 보다 고르게 분산

팬아웃 서비스 전략

  1. 친구 관계나 친구 추천을 관리하기 적합한 그래프 데이터베이스 사용
  2. 사용자 정보 캐시에서 친구들의 정보 조회 -> 데이터베이스에서 스토리 차단 친구 정보 조회 -> 사용자의 새 스토리는 일부 친구들에게만 공유
  3. 친구 목록과 새 스토리의 포스팅 ID를 메시지 큐에 발행
  4. 팬아웃 작업 서버가 메시지 큐에서 데이터를 소비하여 뉴스 피드 데이터를 캐시에 저장
    • 뉴스피드 캐시는 <포스팅 ID, 사용자 ID>의 순서쌍을 보관하는 매핑 테이블
    • 메모리 크기를 적정 수준으로 유지하기 위해 캐시 크기를 제한(해당 값 조정 가능)
    • cache miss?
      • 어떤 사용자가 뉴스 피드에 올라온 수천 개의 스토리를 전부 훑어보는 일이 벌어질 확률은 매우 낮고, 대부분의 사용자는 최신 스토리를 조회
      • 발생 확률 낮음

피드 읽기 흐름 상세 설계

팬아웃 서비스 전략

  1. 사용자가 뉴스 피드 조회 요청
  2. 로드밸런서가 요청을 웹 서버 가운데 하나로 전송
  3. 웹 서버는 피드를 가져오기 위해 뉴스 피드 서비스를 호출
  4. 뉴스 피드 서비스는 뉴스 피드 캐시에서 포스팅 ID 목록을 조회
  5. 뉴스 피드에 표시할 사용자 이름, 사진, 포스팅 콘텐츠, 이미지 등을 사용자 정보 캐시와 포스팅 캐시에서 가져와 완전한 뉴스 피드를 생성
  6. 생성된 뉴스 피드를 JSON 형태로 클라이언트에게 보내, 클라이언트는 해당 피드를 렌더링

캐시 구조

캐시는 뉴스 피드 시스템의 핵심 컴포넌트로, 본 설계안의 경우 캐시를 다섯 계층으로 나눈다.

    
뉴스 피드뉴스 피드  
콘텐츠인기 콘텐츠일반 콘텐츠 
소셜 그래프팔로워팔로잉 
행동‘좋아요’댓글기타
횟수좋아요 횟수댓글 횟수기타
  • 뉴스 피드
    • 뉴스 피드 ID 보관
  • 콘텐츠
    • 포스팅 데이터 보관
    • 인기 콘텐츠는 따로 보관
  • 소셜 그래프
    • 사용자 간 관계 정보 보관
  • 행동(action)
    • 포스팅에 대한 사용자의 행위에 관한 정보 보관
  • 횟수(counter)
    • 팔로어, 팔로잉 횟수 정보도 보관

4단계. 마무리

뉴스 피드 발행과 생성 두 부분에 대한 설계안을 살펴보았다.

아래는 추가적으로 논의할 만한 주제들이다.

  • 데이터베이스 규모 확장
    • 수직적 규모 확장 vs 수평적 규모 확장
    • SQL vs NoSQL
    • master-slave 다중화
    • replica에 대한 read 연산
    • 일관성 모델
    • 데이터베이스 sharding
  • 웹 계층을 무상태로 운영하기
  • 가능한 한 많은 데이터를 캐시할 방법
  • 여러 데이터 센터를 지원할 방법
  • 메시지 큐를 사용하여 컴포넌트 사이의 결합도 낮추기
  • 핵시 메트릭(key metric)에 대한 모니터링
    • 트래픽이 몰리는 시간대의 QPS
    • 사용자가 뉴스 피드를 새로고침 할 때의 지연시간
This post is licensed under CC BY 4.0 by the author.

© Yn3. Some rights reserved.