1-介绍
经常被要求写技术方案, 通过 twitter 来说明如何做一个系统设计的方案.
1)-如果是面试, 一般会用如下的评分标准:
- 可行解:
Work Solution25% - 特定问题:
Special Case20% - 分析能力:
Analysis25% - 权衡:
TradeOff15% - 知识储备:
Knowledge Base15%
2)-4s 分析
-
Scenario: 场景, 最好用 领域语言-业务通用语言描述清楚 需要设计哪些功能, 要设计 多牛的系统Ask/Features/QPS/DAU/Interfaces
-
Services: 服务- 把大的服务拆分为小服务
Split / Application / Module
-
Storage: 存储- 存储
Schema/Data/SQL/NoSQL/File System
-
Scale: 处理可能遇到的问题.Sharding / Optimize / Special Case
2-Twitter Design Post tweet
2-1 Scenario
先问或者自己想, 2个问题.
- 设计哪些功能
- 多大的访问量:
DAU和MAU,一般用月活而不是注册用户来代表一个网站的用户数
1)-Step1 列出所有 Features
Register/LoginUser Profile Display/EditUpload Image/Video/Audio *Search *Post / Share a tweetTimeline / News FeedFollow / Unfollow a user
2)-Step2: Sort , 列出核心功能, 尤其是面试,不可能这么短的时间什么都设计, 不过也可以尝试一下.
下面是一个例子:
Post a TweetTimelineNews FeedFollow / Unfollow a userRegister / Login
3)-并发
并发能力:
- Avg User = 日活跃 x 每个用户的平均请求次数 / 一天多少秒 = 150M x 60 / 86400 = 100k
- 峰值 Peak = Avg x 3 = 300K
- 如果考虑到快速增长, 最好再 x 2 = 600k
- 读的
Qps= 600k - 写的
Qps= 10k
当今的硬件考虑数据库, 这个取决于具体选型,有一些实力特别强劲的:
- 一台
Web Server:1000Qps - 一台
Db:1k - 10k Qps, 设计的是否好非常关键. - 一台
NoSql:10k - 100k Qps, 设计的好也非常关键. - 一台
Memcached: 大概是1M
2-2 Service
将大系统拆分为小服务.
- Replay 重放需求: 过一下需求, 为每个需求都要增加一个服务
- Merge 归并需求: 归并相同的服务
1)-什么是服务?
-
逻辑处理的集合
-
同一类的问题的逻辑 处理归并到同一个
Servivce中 -
整个
System细分为若干个小的Service -
Tweet Service
- Post a tweet
- News Feed Timeline
-
User Service
- Register / Login
-
Relation Service
- follow / unfollow
-
Media Service
- Upload Image / Upload Video
2-3 Storage
1)-Step1 为一个 service 选择一个合适的 Storage
-
数据库系统
Database- 关系型数据库:
SQL Database- 用户信息
User Table
- 用户信息
- 非关系型数据库:
NoSQL Database- 推文:
Tweets - 社交图谱:
Social Graph (followers)
- 推文:
- 关系型数据库:
-
文件系统
File System:- 图片,视频
Media Files
- 图片,视频
-
缓存系统
一个观点:
- 程序 = 算法 + 数据结构
- 系统 = 服务 + 数据存储
2)-Step2 设计 Schema
-
UserRoot
- UserId
- UserCore: username& password & birth & gender
- UserDetail: …
-
FriendFollowRoot
- from_user_id
- to_user_id
-
TweetRoot:
- user_id
- content
- created_at
2-4-New Feed 系统
所有朋友,关注的对象 发的信息的集合.
Pull And Push
-
纯
Pull: 用户查看News Feed的时候, 获取每个好友的前K条, 然后进行多路归并.- 归并排序, 基于内存, 时间一般可以忽略
- 时间成本在于 查询
N个Table, 核心是在于 关注的用户个数. 这次查询.- 可以用
searchAfter: 不要用传统的sort优化单次查询 - 可以用 多线程优化多次
- 可以用
-
纯
Push:- 为每个用户创建一个
List去存储他的NewFeed信息 ; - 也就是写扩散: 写的时候去写 他所有的
followee; - 但是读的时候丛之前
N次读减少为 一次读 ;
- 为每个用户创建一个
-
Push+Pull: 从N次读变为 少数次读 ;
目前热门的 Social App 的模型:
Facebook-PullInstagram-Push+PullTwitter-Pull- 朋友圈 - ?
2-5-前3个的总结
上面搞完之后就是 一个基本可行的方案.
-
Scenario场景:- 和面试官讨论 ;
- 搞清楚需要设计哪些功能 ;
- 分析出所设计的系统大概所需要支持的
Concurrent Users/QPS/Memory/Storage;
-
Service服务:- 合并需要设计功能, 相似的功能整合为一个
Service
- 合并需要设计功能, 相似的功能整合为一个
-
Storage存储:- 对每个
Service选择合适的存储结构 - 细化数据表单
- 画图 展示数据存储和读取的流程
- 对每个
上面3个得到 是一个 Workable Solution 而不是一个 Perfect Solution
2-6 Scale
Step1 - Optimize
- 解决设计缺陷:
Solve ProblemsPullvsPush
- 更多的功能设计:
More FeaturesLike | Follow & UnFollow | Ads
- 特殊情况:
- 明星搞挂微博, 僵尸粉
Step2 - Maintenance
- 鲁棒性
Robust- 一台服务器挂了怎么办
- 扩展性
Scalability:- 如果有流量暴增, 如何扩展
1)-Pull 的问题
- 使用
Cache:Cache的就要考虑How much, 所有的, 最近 1000 天- 过期策略
2)-Push 的问题
-
磁盘问题基本可以忽略: Disk is cheap
-
不活跃用户,
InActive Users- 粉丝排序 Rank followers by weight (for example, last active time)
- 没有登录用户不推送, 然后登录的时候 异步的去同步
-
粉丝数目
follower>> 关注数目followingLady gaga问题 ?- 无解 ? 完全切回
Pull? Push+Pull可解
3)-明星用户
- 明星用户离线计算,
is_super, 明星用户发布的东西配的上缓存.
2-7 选择
既然 Push 的问题也要用 Pull 的思路去解, 那么为什么要用 Push .
什么时候用 Push ?
- 实时性要求不高, 简单,想要偷懒
- 双向好友关系,特殊,比如说朋友圈, 一般就用
push - 非常省钱
什么时候用 Pull ?
- 有明星问题
- 资源充足, 考虑用
redis
2-8 What’s more
1)-Follow && UnFollow 的实现
人和人的关系:
Rdb做的话graphDb做的话
异步的构建优化:
- 批处理 + 合并
Mq
2)-如何存储 Likes
- 同上
Rdb做的话graphDb做的话
上面2个 一个 人→人 , 人→物, 从更全局的角度来看, 都不是 核心域,真正决定留存,北极星指标的还是搜推.
- 所以直接考虑全部 通用化中台, 底层 索引外置到
graphDb是非常好的选择.