【系统设计】设计微博 Twitter 微信朋友圈

661 阅读6分钟

系统设计的评分标准

  • 可行性
  • 特定问题
  • 分析能力
  • 权衡
  • 知识储备

系统设计问题4S分析法

Scenario 场景

  • 需要设计哪些功能,设计的多牛
  • Ask / Features / QPS / DAU / Interfaces

Service 服务

  • 将大系统拆分为小服务
  • Split / Application / Module

Storage 存储

  • 数据如何存储与访问
  • Schema / Data / SQL / NoSQL / File System

Scale 升级

  • 解决缺陷,处理可能遇到的问题
  • Sharding / Optimize / Special Case

Scenario 场景

ASK

  • 需要设计哪些功能?

  • 需要承受多大的访问量? DAU MAU

    • 问这个是需要计算QPS

需要设计哪些功能

  • 第一步 Step 1:Enumerate

    •   把Twitter的功能一个个罗列出来
    •   Register / Login
    •   User Profile Display / Edit
    •   Upload Image / Video *
    •   Search *
    •   Post / Share a tweet
    •   Timeline / News Feed
    •   Follow / Unfollow a user
  • 第二步 Step 2:Sort

    •   选出核心功能,因为你不可能这么短的时间什么都设计
    •   Post a Tweet
    •   Timeline
    •   News Feed
    •   Follow / Unfollow a user
    •   Register / Login

Analysis & Predict

  • 并发用户 Concurrent User

    • 日活跃 * 每个用户平均请求次数 / 一天多少秒 = 150M * 60 / 86400~ 100k

    • 峰值 Peak = Average Concurrent User * 3 ~ 300k

    • 快速增长的产品 Fast Growing

      • MAX peak users in 3 months = Peak users * 2
  • 读频率 Read QPS (Queries Per Second)

    • 300k
  • 写频率 Write QPS

    • 5k

分析出 QPS 有什么用?

  • QPS = 100

    • 用你的笔记本做 Web 服务器就好了
  • QPS = 1k

    • 用一台好点的 Web 服务器就差不多了
    • 需要考虑 Single Point Failure
  • QPS = 1m

    • 需要建设一个1000台 Web 服务器的集群
    • 需要考虑如何 Maintainance(某一台挂了怎么办)
  • QPS和 Web Server (服务器) / Database (数据库) 之间的关系

    • 一台 Web Server 约承受量是 1k 的 QPS (考虑到逻辑处理时间以及数据库查询的瓶颈)
    • 一台 SQL Database 约承受量是 1k 的 QPS(如果 JOIN 和 INDEX query比较多的话,这个值会更小)
    • 一台 NoSQL Database (Cassandra) 约承受量是 10k 的 QPS
    • 一台 NoSQL Database (Memcached) 约承受量是 1M 的 QPS

Service 服务

将大系统拆分为小服务

  • 第一步 Step 1: Replay

    • 重新过一遍每个需求,为每个需求添加一个服务
  • 第二步 Step 2: Merge

    • 归并相同的服务
  • 什么是服务 Service?

    • 可以认为是逻辑处理的整合
    • 对于同一类问题的逻辑处理归并在一个 Service 中
    • 把整个 System 细分为若干个小的 Service

Storage 存储

数据如何存储与访问

  • 关系型数据库 SQL Database

    • 小调查:Twitter的哪些信息适合放在关系型数据库中?
    • 用户信息 User Table
  • 非关系型数据库 NoSQL Database

    • 小调查:Twitter的哪些信息适合放在非关系型数据库中?
    • 推文 Tweets
    • 社交图谱 Social Graph (followers)
  • 文件系统 File System

    • 小调查:Twitter的哪些信息适合放在文件系统中?
    • 图片、视频 Media Files

步骤:

  • 第一步 Step 1: Select

    • 为每个 Application / Service 选择合适的存储结构
  • 第二步 Step 2: Schema

    • 细化数据表结构

程序 = 算法 + 数据结构

系统 = 服务 + 数据存储

Interviewer: Please design schema

Interviewer: News Feed 如何存取?

什么是新鲜事 News Feed?

  • 你登陆 Facebook / Twitter / 朋友圈 之后看到的信息流
  • 你的所有朋友发的信息的集合

Pull Model

  • 算法

    • 在用户查看News Feed时,获取每个好友的前100条Tweets,合并出前100条News Feed
    • K路归并算法 Merge K Sorted Arrays
  • 复杂度分析

    • News Feed => 假如有N个关注对象,则为N次 DB Reads的时间(读DB非常耗费性能的) + K路归并时间(可忽略)

      • 为什么K路归并的时间可以忽略?
    • Post a tweet => 1次DB Write的时间

Interviewer: Pull模型有什么缺陷么?

Push Model

  • 算法

    • 为每个用户建一个List存储他的News Feed信息

    • 用户发一个Tweet之后,将该推文逐个推送到每个用户的News Feed List中

      • 关键词:Fanout
    • 用户需要查看News Feed时,只需要从该News Feed List中读取最新的100条即可

  • 复杂度分析

    • News Feed => 1次DB Read

    • Post a tweet => N个粉丝,需要N次DB Writes

      • 好处是可以用异步任务在后台执行,无需用户等待
  • News Feed Table

Interviewer: Push模型有缺陷么?

Scale 扩展

如何优化系统

  • 第一步 Step 1: Optimize

    • 解决设计缺陷 Solve Problems

      • Pull vs Push, Normalize vs De-normalize
    • 更多功能设计 More Features

      • Edit, Delete, Media, Ads
    • 一些特殊用例 Special Cases

      • Lady Gaga, Inactive Users
  • 第二步 Step 2: Maintenance

    • 鲁棒性 Robust

      • 如果有一台服务器/数据库挂了怎么办
    • 扩展性 Scalability

      • 如果有流量暴增,如何扩展

解决Pull的缺陷

  • 最慢的部分发生在用户读请求时(需要耗费用户等待时间)

    • 在 DB 访问之前加入Cache

    • Cache 每个用户的 Timeline

      • N次DB请求 → N次Cache请求 (N是你关注的好友个数 )
      • Trade off: Cache所有的?Cache最近的1000条?
    • Cache 每个用户的 News Feed

      • 没有Cache News Feed的用户:归并N个用户最近的100条Tweets,然后取出结果的前100条
      • 有Cache News Feed的用户:归并N个用户的在某个时间戳之后的所有Tweets
  • 对比MySQL 和 Memcached 的 QPS

    • Memcached QPS / MySQL QPS ~ 100

解决Push的缺陷

  • 浪费更多的存储空间 Disk

    • 与Pull模型将News Feed存在内存(Memory)中相比
    • Push模型将News Feed存在硬盘(Disk)里完全不是个事儿
    • Disk is cheap
  • 不活跃用户 Inactive Users

    • 粉丝排序 Rank followers by weight (for example, last login time)
  • 粉丝数目 followers >> 关注数目 following

    • Lady Gaga问题

    • 无解?完全切换回Pull?

    • Trade off: Pull + Push vs Pull

Lady Gaga

  • 粉丝 Followers 65.5M

    • Justin Bieber 80M on Instagram
    • 谢娜 90M on Weibo
    • 以上数据来自2017年3月
  • Push 的挑战

    • Fanout 的过程可能需要几个小时!
  • 面试时错误的回答方案

    • 既然 Push 不行,那我们就切换到 Pull 吧!
  • 正确的思路

    • 尝试在现有的模型下做最小的改动来优化

      • 比如多加几台用于做 Push 任务的机器,Problem Solved!
    • 对长期的增长进行估计,并评估是否值得转换整个模型

Push 结合 Pull 的优化方案

  • 普通的用户仍然 Push
  • 将 Lady Gaga 这类的用户,标记为明星用户
  • 对于明星用户,不 Push 到用户的 News Feed 中
  • 当用户需要的时候,来明星用户的 Timeline 里取,并合并到 News Feed 里

摇摆问题

  • 明星定义

    • followers > 1m
  • 邓超掉粉

    • 邓超某天不停的发帖刷屏,于是大家果取关,一天掉了几十万粉
  • 解决方法

    • 明星用户发 Tweet 之后,依然继续 Push 他们的 Tweet 到所有用户的 News Feed 里

      • 原来的代码完全不用改了
    • 将关注对象中的明星用户的 Timeline 与自己的 News Feed 进行合并后展示

      • 但并不存储进自己的 News Feed 列表,因为 Push 会来负责这个事情。

Pull vs Push

取关问题