曾在创业的时候,公司刚开始做在线直播的消息分发服务,礼物弹幕什么的。当时使用的是Node.js。当时虽然已经调查日活跃暴增的解决的集群方案,但由于不够重视。等到日活跃真的增加的时候,系统撑不住了,客户体验极差。后果也是很严重的,导致业务无法正常运营,因为一旦启动,人上来就撑不住了。本以为集群很简单,但是放在内存里的数据是不能够被多个进程,或者多台机器共享的,前移成本远不是之前想象的一天就能完成的。
系统设计(System desgin)是针对一相业务需求,设计系统架构,子业务模块,接口细节,数据存储的一个过程。通常要对给定的需求有一个可行的解决方案。
无论你是想创业,还是想进一步走向架构师,还是程序Leader,系统设计都是必不可少的知识储备
系统设计严格来说没有标准答案,当有一个可行解的时候,还要不断的挑战设计的各个部分,如果服务器挂了怎么办,如果日活跃多了怎么办?
设计一旦完成,作为设计者绝不可以武断的因为些许挑战就推翻重来,无论是人力成本还是时间成本都是巨大的,迁移也会给统稳定性带来巨大的风险。
##数据存储
如果说程序 = 算法 + 数据结构
那么系统 = 服务 + 数据存储
通常,不同的存储媒介有不同的成本,大小,持久性的特点
- 内存,访问速度快,有上限,通常一台常见的电脑8个G左右,断电之后数据会丢失
- SQL,结构化数据,支持事务处理,访问速度要比内存慢,但是存储量大,可持久保存
- NO-SQL,结构化数据,速度比SQL快,存储量大,可持久
- 文件系统,非结构化数据,例如视频,图片,音频,访问速度比内存慢,同样存储量大,可持久保存
##系统设计流程
那么当你遇到如何设计登录,微博,即时通讯(IM),爬虫,附近的人,推荐,交易系统等等,需要如何开始吹牛逼呢?不对,是从哪些角度开始着手呢?
###场景假设Scenario
- 主要功能,比如说用户A发微博,其他用户阅读。再比如说IM需要A,B聊天互相可达。爬虫的话能够抓取大量数据存储,并通过一定的方式展示出来。(这里除了爬虫系统,其他系统都是读 > 写的)
- 日活跃估计,如果系统只是一个宿舍的人在用,那么一台笔记本就可以了。如果是10万日活跃呢?又或者说是像明星公司一样上亿的日活跃呢。
- 有了日活跃,我们就可以估计QPS, 即每秒达到服务的请求数目, 假设我们的服务有5千万日活跃用户,月活用户1个亿(通常MAU = 2~5倍的DAU)
# 我们假设每个用户大概浏览10页网页,一天86400秒, 那么估计读QPS:
QPS = 50000000 * 10 / 86400 = 1736
# 假设该产品高峰时期,是正常QPS的3倍,通常高峰QPS = 2 ~ 9倍的QPS
Peak QPS = QPS * 3 / 86400.0 = 5787
# 假设平均每个用户发布1个内容,那么写QPS
QPS = 50000000 * 1 / 86400 = 578
PEAK QPS = QPS * 3 = 1734
###服务拆分Service
根据系统的具体业务,拆分业务为小的子服务:
- 如果是微博,我们最少需要一个发布服务,消息读的服务。
- 如果是IM,我们可能需要在线服务,消息发送,消息推送服务
- 如果爬虫,需要抓取服务,爬虫派遣服务。
- 还有是附近的人的距离计算,推荐系统的Feature推荐服务等等
###存储类型Storage
有了之前的读写QPS,我们可以选择用什么样的数据库,是否需要支持transition呢,数量级假设如下
SQL 支持 1k QPS, 支持Transaction
Cassandra 支持 10K QPS
Memecache 支持 100K ~ 1M QPS
一台机器如果不够的话,可以考虑通过多台分担服务压力
PS:事务(Transaction),通常以银行交易举例,例如A转账给B两百元,此时A-=200;B+=200。如果第一步出错,B凭空多200块钱。反之A凭空少200块钱。事务是指,这两个操作需要同时成功,遇到任意失败,回退到初始状态。
###升级维护Scale
- 如果只用一台机器,那么要考虑单点失败问题(Single Point Failure)
- 数据需要定期做备份的(Backup),如果出现系统故障,或者运营事故,可以回滚到一个时间节点
- 需要做Replica备份,多个Replica可以分担数据库的读请求。
- 如果美国用户,访问中国的服务器速度慢,是否可以考虑数据库地域存储。
- 集群如何添加,删除节点,如何判断一个节点已经死掉了。
- 通常数据库,或者复杂计算结果是需要内存缓存的。那么缓存策略怎么选择呢?常见的有LRU, LFU
- 单台机器磁盘不够了,通过横向,纵向实现拓展,分摊存储压力
- 如果系统出现故障,如何快速定位,和解决,或者会滚呢
- 有恶意用户不断写入咋办,如果有用户就是觉得好玩,上传1T的一个文件呢
延迟
L1 cache reference ......................... 0.5 ns
Branch mispredict ............................ 5 ns
L2 cache reference ........................... 7 ns
Mutex lock/unlock ........................... 25 ns
Main memory reference ...................... 100 ns
Compress 1K bytes with Zippy ............. 3,000 ns = 3 µs
Send 2K bytes over 1 Gbps network ....... 20,000 ns = 20 µs
SSD random read ........................ 150,000 ns = 150 µs
Read 1 MB sequentially from memory ..... 250,000 ns = 250 µs
Round trip within same datacenter ...... 500,000 ns = 0.5 ms
Read 1 MB sequentially from SSD* ..... 1,000,000 ns = 1 ms #Assuming ~1GB/sec SSD
Disk seek ........................... 10,000,000 ns = 10 ms
Read 1 MB sequentially from disk .... 20,000,000 ns = 20 ms
Send packet CA->Netherlands->CA .... 150,000,000 ns = 150 ms
More
http://norvig.com/21-days.html#answers
–END–