甲乙小朋友的房子

甲乙小朋友很笨,但甲乙小朋友不会放弃

0%

系统设计-新鲜事系统

系统设计面试

  • 设计某系统
    • 设计微博
    • 设计Facebook
    • 设计滴滴、Uber
    • 设计微信
    • 设计点评
    • 设计短网址系统 Tiny URL
    • 设计NoSQL数据库
  • 找问题
    • 网站挂了怎么办
    • 网站太慢怎么办
    • 流量增长怎么办

设计新鲜事系统——类似微博、twitter的系统。

  • 什么是新鲜事系统?news feed ?
    • 朋友圈、微博的信息流
    • 朋友信息集合
  • 核心因素?
    • 关注、被关注
    • 每个人看到的新鲜事是不同的

常见错误:扮演关键词大师(负载均衡、Memcache、NodeJS、MongoDB、MySQL、Sharding、Consistent Hashing、Master Slave、HDFS、Hadoop...)

思考:或许只有两个用户呢?

系统设计面试评分标准:

系统设计4S分析法

  • Scenario 场景
    • 需要设计哪些功能、到哪个程度
    • 询问
  • Service 服务
    • 将大系统拆分为小服务
    • 拆分、Application、模块化
  • Storage 存储(比较核心的部分)
    • 数据如何存储与访问
    • Schema/Data/SQL/NoSQL/File System
  • Scale 升级
    • 解决缺陷,处理可能遇到的问题
    • Sharding/ Optimize / Special Case

设计Twitter

场景

场景连问

  • 需要设计哪些功能?
  • 需要承受多大访问量?
    • DAU - 150M+ (日活跃用户 - DAU - Daily Active User)
    • MAU 313M

场景

  • 并发用户
    • 日活跃*每个用户平均请求次数/一天多少秒 = ... = 100k
    • 峰值 Peak = Average Concurrent User * 3 ~ 300k
    • 快速增长的产品 —— MAX peak users in 3 mouth = 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服务器集群
    • 需要考虑维护问题(万一一台挂了)

QPS和Web Server(服务器) / Database(数据库) 之间的关系

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

服务

将大系统拆分为小服务

  • Replay 重放需求
  • Merge 归并需求

什么是服务 Service?

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

服务拆解

一个总路由,对应四个模块:

存储 —— 最重要

数据如何存储与访问

  1. 为每个 Service 选择存储结构
  2. 细化表结构

程序 = 算法 + 数据结构

系统 = 服务 + 数据存储

数据如何存储与访问

  • 内存
    • 一些临时的,丢了没关系的数据,可以不用持久化
  • 关系型数据库 SQL Database
    • 结构化数据 适合放在关系型数据库中
    • 用户信息 User Table
  • 非关系型数据库 NoSQL Database
    • 小调查:Twitter的哪些信息适合放在非关系型数据库中?
    • 推文 Tweets
    • 社交图谱 Social Graph (followers)
  • 文件系统 File System
    • 小调查:非结构化数据 适合放在文件系统中
    • 图片、视频 Media Files

也就是可以按照如下图所示设计Twitter的数据存储:

结构化数据如何细化表结构?

获取feed

Pull模型 —— 主动模型

用户查看news feed时,获取每个好友前100条微博,合并出前100条——K路归并算法

复杂度:

  • News Feed --> 假如有N个关注对象,则复杂度 = N次db read(不可接受的复杂度) + K路归并(可忽略)
  • Post a tweet --> 一次db write

pull 原理图:

  1. 用户请求消息
  2. 获取关注列表
  3. 获取关注列表的前100tweets
  4. merge之后返回

pull模型的缺陷:N次db reads太慢了,而且它发生在用户获得news feed的请求过程中,简直致命

Push模型 —— 被动模型

  1. 为用户建一个list,每个用户的好友发的tweets都在这个用户的list里。(叫做fanout)
  2. 用户想看时,只需要从该list里读取最新的100条即可

复杂度分析:

  • News feed --> 1次db read
  • post a tweet --> n个粉丝,需要n次db writes ,虽然没有read快,但是可以异步执行的

push模型的缺陷:不及时。明星的followers的数目可能很大,用户延迟慢的很。

Poll与Push的选择

考虑到僵尸粉与活跃用户,很多都是pull模型,为了及时。

热门Social App的模型 • Facebook – Pull • Instagram – Push + Pull • Twitter – Pull

误区 • 不坚定想法,摇摆不定 • 不能表现出Tradeoff的能力 • 无法解决特定的问题

扩展

第一步 Step 1: Optimize

  • 解决设计缺陷
  • Pull vs Push——Normalize vs De-normalize
  • 更多功能设计 :Edit, Delete, Media, Ads
  • 一些特殊用例 :Lady Gaga, Inactive Users

第二步 Step 2: Maintenance

  • 鲁棒性 Robust:如果有一台服务器/数据库挂了怎么办
  • 扩展性 Scalability:如果有流量暴增,如何扩展

解决pull的缺陷

最慢的部分发生在用户读请求时,那么可以:

  • 在DB访问之前加入cache
  • cache每个用户的timeline:
    • N次DB请求 --> N次cache请求
    • trade off : 可以考虑只考虑最近的1000条之类的
  • cache每个用户的news feed
    • 没有cache news feed的用户:归并N个用户最近的100条tweets,然后取出结果的前100条
    • 有cache news feed的用户:归并N个用户在某个时间戳之后的所有tweets

解决push缺陷

  • 浪费空间
    • 但其实没啥
  • 不活跃用户
    • 粉丝排序。但也没啥作用
  • 大量粉丝问题,无解。因此可以尝试在现有的模型下

进行优化。还可以对长期增长进行估计,并评估是否值得转化整个模型。

结合

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,我们仍然要学习Push?

  • 系统设计不是选择一个最好的方案
  • 而是选择一个最合适的方案
  • 如果你没有很大的流量,Push是最经济最省力的做法
  • 系统设计面试也并不是期望你答出最优的解决方法,而是从你的分析当中判断你对系统的理解和知识储备。

什么时候用 Push?

  • 资源少
  • 想偷懒,少写代码
  • 实时性要求不高
  • 用户发帖比较少
  • 双向好友关系,没有明星问题(比如朋友圈)

什么时候用 Pull ?

  • 资源充足
  • 实时性要求高
  • 用户发帖很多
  • 单向好友关系,有明星问题