System design summary
system design
https://github.com/donnemartin/system-design-primer
Performance vs scalability
scalability 这里面的伸缩性是指指标的。当系统有较高的负载时,每个用户仍然能够有较好的响应时,我们说他系统伸缩性强。
Performance 就是指一个请求的响应越快,自然说性能越高
如何才能让系统有更好的可伸缩性?
需要在系统设计初就提前考虑好系统设计,提前知道可能的问题点,性能点等等。
那么具体的系统设计如下:
Latency vs throughput
延时:单个请求的延时
吞吐量:单位时间内处理的请求量
Availability vs consistency
CAP理论:对于分布式系统,发生网络分区是一定要考虑的,因此在发生网络分区的情况下,对于C和A只能二选一。
当发生网络分区时,如果你允许用户操作,那么就会造成网络分区之间的数据不一致。
当发生网络分区时,如果你不允许用户操作,那么不同分区之间的数据不会因此而不一致,但这就不能保证可用性。
Consistency patterns
Weak consistency 通话视频,丢一些也没关系,最大限度保证通畅
Eventual consistency 可以忍受延时,保证最终一致性
Strong consistency 强一致性,比如Mysql 事务,事务执行后,第一次查询就要是最新的数据
Availability patterns
Fail-over : Active-passive 主从结构,当主节点挂掉后,从节点自动升级为主节点向外提供服务,比如redis哨兵,mysql主从。 Active-active 主主结构,集群中各个节点都向外提供服务,当某个节点挂机后,负载均衡器不将流量负载到宕机节点即可。比如一些分布式数据库,kafka集群等。
Availability in numbers
可靠性的一些指标,比如要达到几个9
99.9% availability - three 9s
Duration | Acceptable downtime |
---|---|
Downtime per year | 8h 45min 57s |
Downtime per month | 43m 49.7s |
Downtime per week | 10m 4.8s |
Downtime per day | 1m 26.4s |
99.99% availability - four 9s
Duration | Acceptable downtime |
---|---|
Downtime per year | 52min 35.7s |
Downtime per month | 4m 23s |
Downtime per week | 1m 5s |
Downtime per day | 8.6s |
一些常见的系统组件
DNS,用DNS做负载均衡的
CDN,某些云服务器厂商的CDN原理。我有一个域名keboom.site。然后我可以访问此域名拿到一些文件。在云厂商处配置keboom.site,他会返回给你一个类似 alicloud.keboom.site的域名,前端代码在请求资源时,使用 alicloud.keboom.site来获取资源。云厂商会将keboom.site 的资源缓存到他们的服务器上。前端程序将访问云厂商缓存的资源,这大概就是CDN原理。
负载均衡,平时我们说的有nginx,这其实是在application 层。对于负载均衡在网络协议中,layer 4 也是可以做的,我记得是有些硬件设备支持这种层次的协议。
数据库
关系式数据库,特点是他支持事务,关系型表结构。
一些讨论点: 主从:分主从的话,比如读写分离,那么就要有手段做读写分离 主主:数据冲突,事务性的破坏,需要控制访问哪个主
对于数据库主主,主从,共同的缺点:数据延时问题(主同步不及时,此时主挂机,则数据丢失),数据同步问题(同步数据,消耗性能) 联邦:国外是这么叫的,对于国内来说,他可能说叫根据业务进行数据切分。缺点:如果多数据库join就很麻烦。多数据库事务。
切片:数据做分区,切片。mysql是有partition功能的,可对数据做分区(但这只是mysql内部做的优化,如果数据量足够大,仅仅分区还是不够,可能还是要将数据分到多个数据库多个服务器,然后做hash)。当然有也人为的对表做切分,比如对表加后缀然后做hash,这样人为做切分。缺点很明显就是数据切分后,我们的查询逻辑变得复杂。
反规范:可以消除一些join,但带来一些冗余。
SQL优化:建表时:比如字段的选择,尽可能让表结构更小。SQL查询时,注意建立索引,并且能够使用到索引。慢查询排查等。
NoSQL
虽然一些NoSQL数据库声称自己支持事务,但是网络上并不太认同。
一般来说他们 可用性 > 一致性
key value:典型的redis等,作为分布式缓存使用。
doc:如MongoDB,文档型,数据结构更加灵活些,json类型的文档不必要每个字段都必须一致。如果你的数据结构层级较深,结构没有那么规整,那么可以考虑使用文档型
列式存储:大数据相关,HBase clickhouse等,特点是数据压缩效率高,支持大量的写入,大数据情形下表现好。比如日志存储,或者一些数据归档等,作为数据仓库等使用。
图形:社交关系
Cache
从头到尾,客户端缓存,CDN缓存,web sever缓存,application 缓存,分布式缓存,数据库缓存
cache pattern: 经典的redis 和 数据库的更新
查询时: cache aside:查询cache,如果cache没有,则从数据库中查询出来放到缓存中,然后返回。
缺点: 1.时间变长(查询缓存、更新数据库、更新缓存)2. 当数据库数据更新时,缓存中数据需要做过期或修改或删除等操作。3. 当缓存服务器重启,则所有缓存需要重新加载
更新时:
- 先更新数据库再跟新redis
- 先更新redis在更新数据库
以上两种方式都是有一定时间的数据不一致。
异步
消息队列—背压:生产者生产消息放到消息队列服务器的内存中,消费者进行消费时,直接从内存中读取。这样是效率最高的。如果队列中数据过多导致服务器内存不足,则消息势必存储到磁盘中。这时消费者再来进行消费,则需要先从磁盘中随机读,将数据加载到内存中,才能进行消费,这样速度就会慢。那么通过背压的方式,当内存满时,则同时生产者减慢或者暂停生产。