SCALE FROM ZERO TO MILLIONS OF USERS
- 总览
-
DNS
-
CDN
-
LB
-
Server
-
MQ
-
DB
-
Cache
-
Tool
-
数据库
-
SQL vs NoSQL
-
关系型数据库
-
事务
-
成熟
-
非关系型数据库
-
低延迟
-
非结构化数据,json
-
大数据
-
水平拓展 vs 垂直拓展
-
垂直
-
简单(单机)
-
水平(sharding)
-
大数据
-
fallover
-
备份
-
缓存
-
何时用
-
和数据库的一致性(cache aside)
-
过期策略
-
逐出策略(LFU)
-
CDN
-
静态资源缓存
-
过期时间
-
fallback
-
主动失效
-
增加object version
-
多主机房
-
流量调度策略(就近、用户数据户口固定(GeoDNS))
-
灾备切换
-
数据同步策略
-
sharding
-
sharding key的选择,均匀(user id)
-
re-sharding(一致性哈希)
-
热key(手动运维分布)
-
join查询跨sharding(反范式化设计)
BACK-OF-THE-ENVELOPE ESTIMATION
- 2的次方(KB,MB,GB,TB)
- QPS的估算
- 存储的估算
A FRAMEWORK FOR SYSTEM DESIGN INTERVIEWS
- 4steps
DESIGN A RATE LIMITER
-
API限流器的好处
-
防止DoS攻击(深入)
-
减小服务端成本
-
理解需求
-
Client侧?Server侧?
-
限流纬度:IP?UID?
-
QPS
-
分布式
-
实现方式:middleware
-
限流http返回429
-
算法
-
Token bucket
-
广泛使用
-
固定大小的桶,定时固定速率加令牌;一个请求消费一个令牌,桶中无令牌则被丢弃
-
关键参数:桶大小;令牌发放速度
-
拓展,定制化限流:一个API一个桶;一个IP一个桶
-
优点:简单;内存使用率低;短期流量峰值时,能保证限流准确性(对后来的请求公平、通过可能性均匀)
-
缺点:参数多,难以控制
-
Leakding bucket
-
类似token bucket。用FIFO的队列代替
-
关键参数:队列大小;出队列速度
-
缺点:参数多;短期流量峰值时,不能保证限流准确性(后来的请求大概率被抛弃,因为前面的请求阻塞在队列里)
-
Fixed window counter
- 固定时间周期内只允许固定个数的请求通过;counter计数
- 关键参数:单位时间内的通过请求数
- 优点:内存使用少;方便调整参数
- 缺点:短期流量峰值时,不能保证限流准确性(如图,时间区间不均匀)
- Sliding window log
-
优化了Fixed window counter的分布不均问题;记录每个请求时间戳,计算当前请求时间戳前的时间窗口内的请求数,决定是否通过请求
-
关键参数:单位时间内的通过请求数
-
缺点:内存占用高
-
Sliding window counter
-
结合固定窗口计数和固定窗口log; Requests in current window + requests in the previous window * overlap percentage of the rolling window and previous window
-
比log法节省存储;比counter法发生高峰过滤不均的概率低(几乎忽略不计)
-
架构设计
-
redis
-
存counter、rule、log等
-
rua脚本、有序集合保证分布式的一致性
-
MQ:作为死信队列
-
数据中心
-
多主同步
DESIGN CONSISTENT HASHING
-
目的
-
使得数据均匀分布多个节点,从而当增减节点时的数据迁移较少
-
传统取余哈希的不足
-
定义
-
k个key,n个节点,当节点数调整,只有k/n个key需要调整
-
算法
-
hash ring
-
定义:传统取模法是对节点数量进行取模,而一致性Hash算法是对 2^32 取模,一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0-2^32-1(即哈希值是一个32位无符号整形),整个哈希环如下,从 0 ~ 2^32-1 代表的分别是一个个的节点
- 增加(减去)节点
-
问题(缺点)
-
增加、减去节点后,每个节点的分区范围不均匀
-
节点在ring上,原本就分布不均
-
虚拟节点
-
解决ring的两个问题
-
一个真实节点对应更多虚拟节点;通常将虚拟节点数设置为32甚至更大,因此即使很少的服务节点也能做到相对均匀的数据分布。这也是 Dubbo 负载均衡中有一种一致性哈希负载均衡的实现思想
- demo
DESIGN A KEY-VALUE STORE A key-value store
-
理解问题
-
key size
-
海量数据
-
高可用
-
低延迟
-
一致性
-
单体存储
-
数据压缩
-
高频数据内存,其余磁盘
-
很容易用光单机容量,需要分布式存储
-
分布式存储
-
CAP:三者满足其二。理论上无法满足CA,因为必须存在分区容错性
-
架构设计
-
数据分区
-
数据均匀分布到各个服务器节点
-
增减服务器时,最小化数据迁移
-
解决上述两点:一致性哈希
-
数据复制
-
备份到不同虚拟节点
-
备份到不同物理节点
-
备份到不同集群
-
数据一致性
-
Quorum理论
-
N,W,R
-
tradeoff between latency and consistency。W,R为1,对应读写操作很快;W+R>N,保证一致性
-
一致性级别
-
强一致性
-
弱一致性、最终一致性
-
如何保证最终一致性
-
vector clock(server:version)
- 缺点:客户端复杂;vector过长(设定舍弃长度的阈值)
-
失败探测
-
gossip协议(深入)
-
每个节点维护节点id和对应心跳counter的list
-
定期自增,并选择部分节点广播
-
超过时间阈值仍不更新counter的节点认为下线节点
-
处理失败节点
-
处理短期失败:hinted handoff。其他节点临时代处理,恢复后push下线期间数据
-
处理长期失败:反熵协议。强制重分配所有数据
-
merkle tree:MT是一种树,大多数是二叉树,也可以多叉树; Merkle Tree的叶子节点的value是数据集合的单元数据或者单元数据HASH。 非叶子节点的value是根据它下面所有的叶子节点值,然后按照Hash算法计算而得出的blog.csdn.net/wo541075754…
-
节点功能总结
-
client api
-
失败探测
-
数据分区同步
-
冲突检测
-
数据存储
-
读写流程
-
写
-
log file,磁盘 (顺序IO,快)
-
写缓存
-
异步写入磁盘 SSTable(深入)
-
读
- 读缓存
- 缓存无,则读磁盘。先用布隆过滤器过滤
DESIGN A UNIQUE ID GENERATOR IN DISTRIBUTED SYSTEMS
-
数据库自增主键,无法使用在分布式环境
-
明确需求
-
unique,sortable
-
64bit
-
10kQPS
-
算法
-
多主自增主键
-
自增k(k个主)
-
缺点:
-
无法全局时序性
-
增减节点不方便
-
UUID
-
128bit,32位16进制数,基于机器的一些属性生成www.jianshu.com/p/da6dae36c…
-
优点
-
简单
-
节点独立,方便增减
-
缺点
-
128bit,大
-
没有时序性
-
16进制,不是纯数字
-
ticket server
-
单独一个数据库自增主键
-
缺点:单点
-
雪花算法
-
milli sec时间戳+集群id+机器id+seq for 每milli sec。64bit
-
可用69年,for 时间戳
-
4096 QS for each milli sec(409.6kQPS)
-
缺点:强依赖时钟。机器时钟回拨则不可用
DESIGN A URL SHORTENER
-
问题评估
-
WPS:1160
-
QPS:11600
-
存储量:365 billion records * 100length = 365TB
-
http3xx
-
301:永久重定向;浏览器缓存
-
302:临时重定向;直接请求服务器
-
生成短链
-
www.tinyurl.com/{hashValue}…](p3-juejin.byteimg.com/tos-cn-i-k3…?)
-
要求:唯一,双向映射(一一对应)
-
确定hash value长度;0-9,a-Z,长度n,则有62的n次方>365billion->n=7
-
哈希+解决冲突
-
CRC32、MD5、SHA-1等。但是长度远大于7;取前7位,并用线性探测法解决冲突
-
判断短链是否重复
-
base62转化法
-
判断长链是否重复
-
全局唯一ID,转化成62进制数,作为hash value
-
两者对比
-
短链长度是否固定
-
是否需要全局唯一ID
-
是否可能冲突
-
是否有规律可循导致安全隐患
-
数据存储(关系型数据库)
DESIGN A WEB CRAWLER
-
策略
-
DFS or BFS
-
DFS会递归爆栈,一般不会使用
-
BFS缺点:
-
短期对一个host会大量请求,会被拒绝
-
无法体现URL的优先级
-
URL frontier:解决BFS的缺点
-
一个队列一个host
-
n个线程worker
-
优先级、URL时效性过滤器
-
URL存储
-
磁盘+buffer
DESIGN A NOTIFICATION SYSTEM
- Push,SMS,Email
- 近实时系统
- 架构
-
存储
-
mobile token
-
phone number
-
email address
-
高阶架构
-
业务微服务:触发器
-
Notification 服务:给业务微服务提供接口;发MQ;基础校验
-
MQ:解耦,削峰;各个功能互不影响
-
MQ consumer
-
三方service
-
用户端
- 限流器(用户粒度)
- 死信队列,重试,报警
- MQ监控
- 用户行为埋点上报
DESIGN A NEWS FEED SYSTEM
- 发作品架构
-
web入口:鉴权;限流
-
Post服务:存储作品内容
-
Fanout服务:更新好友feed列表
-
push model:在写操作时更新所有好友feed列表(发布作品)
-
实时性;拉feed快
-
好友多会有hotkey,写慢;僵尸号浪费计算
-
pull model:在读操作时计算最新的feed列表(拉feed)
-
优缺点同push相反
-
最终:结合
-
大v好友多的用户发布作品:pull
-
普通用户:push
-
过程
-
从图数据库获取好友关系(深入)
-
从cache or db获取好友user信息,过滤屏蔽用户
-
发MQ
-
存post id->user id
-
获取feed架构
-
缓存的内容
-
ids of feed news
-
news content
-
user relation
-
user action(like)
DESIGN A CHAT SYSTEM
-
server如何给client发消息
-
polling。客户端轮询。成本高
-
long polling。长轮询。同样成本较高
-
webSocket。双工TCP持久长连接。最为常用
-
架构
-
无状态服务(传统的http req、resp的接口)
-
登录
-
用户个人信息
-
有状态服务
-
chat。持久的长连接
-
三方
-
push
-
存储
-
业务特性
-
量大
-
读写1:1
-
最近的数据访问高频
-
但是会有全局搜素诉求
-
KV NoSQL,不适合用关系型数据库
-
数据模型设计
-
message id
-
group id+message id
-
为何不用消息时间戳?可能重复
-
id不用自增主键和雪花算法。local generator
-
单聊
- 多设备同步(各端维护current max message id)
-
群聊
-
小群(微信)
-
大群
-
-
用户登录态同步
-
用户长连接心跳
DESIGN A SEARCH AUTOCOMPLETE SYSTEM
-
词频统计
-
查询的词和它的频次
-
搜索
-
关系型数据库
-
太慢
-
Trie
-
步骤
-
找到前缀 O(p)
-
找到所有孩子节点O(c)
-
孩子节点排序O(clogc)
-
优化成准O(1)
-
限制前缀长度
-
每个节点缓存
-
缓存一致性
-
周期性即可,没有必要实时更新
-
weekly snapshot of DB
-
架构
-
Trie DB和Trie Cache的更新
-
周期性重建,用完整的一颗新树代替旧树
-
避免实时单节点更新
-
避免实时删除节点。对于实时的暴力过滤,可以在trie前加业务过滤层
-
Trie DB 分片平衡
-
拓展
-
实时搜索?热词
-
多语言
-
多国家
-
适合搜索的数据库。ES?Mongo
DESIGN YOUTUBE
- CDN
-
API: feed,下发视频URL,更新视频meta
-
上传视频
-
Origin Storage:存储用户原始视频。(BLOB数据库,对象存储)(深入)
-
转码服务:视频encoding,转成MPEG等格式(深入)
-
转码存储:encoded的视频存储
-
步骤
-
并行A
-
通过API服务保持视频meta信息,文件名用户id等
-
存到Meta信息存储
-
并行B
-
上传到original存储
-
调用转码服务
-
并行a:完成转码MQ;消费者更新meta
-
并行b:转码存储;CDN
-
视频播放
-
视频流协议:MPEG等;不同的编码方式,支持不同的播放器
-
CDN
-
视频存储
-
码率
-
文件格式
-
处理流
-
系统优化
-
视频切分,并发上传
-
上传中心分国家部署,就近选择
-
数据安全:api鉴权后才可以上传;视频内容加密、水印
-
存储节省:热点视频才上CDN;非常冷门视频无需存储转码内容,只存original,转码内容按需实时加载
DESIGN GOOGLE DRIVE
-
需求
-
上传、下载文件
-
支持任何类型
-
API
-
上传。上传类型:新建;继续
-
下载
-
冲突
-
两个用户同时修改一个文件
-
版本号,CAS(深入多人实时在线编辑)
-
架构
-
block server:上传文件优化处理的server。文件分块Block;增量更新上传(至传有变化的block);压缩;加密
-
cloud storage:存储常规数据
-
cold storage:不活跃数据
-
缓存、DB数组一致性:采用关系型数据库;Cache Aside Pattern(旁路缓存)coolshell.cn/articles/17…
-
存储设计
-
user
-
device
-
namespace
-
file
-
file version:只读。快照
-
block
-
上传
-
save file meta
-
上传文件到cloud storage
-
上传完成,触发调用API更新meta file status
-
下载
-
notification
-
节省存储
-
限制单个file的version的上限。对应的meta,file block
-
短时间快速编辑的文件只保留最新的version
-
cold storage