【系统设计】如何设计一个牛X的系统?这三点很重要

       今天这篇文章是我看完极客时间《高并发系统设计40问》前几章后做的一个读书笔记,将里面的重点都总结出来了,大家如果认真看完,应该会对系统设计有一个比较清晰的框架了。 

       什么样的系统才是一个牛逼的系统呢?如果一个系统满足这三点,我们就可以说它是个牛逼的系统了:高性能、高可用、可拓展。那我们如何按照这三点来设计系统呢?下面将一一为大家介绍。

1. 高性能

性能优化原则

1. 问题导向:针对目前存在或未来会出现的问题进行优化。

2. 二八原则:20%精力解决80%性能问题。

3. 需要数据支持:优化的效果是需要数据证明,提升了多少响应速度、吞吐量等。

4. 优化过程是持续的:换句话说,只要系统不断迭代,优化就要不断进行。

性能度量指标

一般度量性能的指标是接口响应时间。单次响应时间是没有意义的,我们一般需要度量一段时间的响应情况,所以会用到如下特征值:

1. 平均值:时间段内所有请求时间除以时间(敏感度差)。

2. 最大值:取最长响应时间(太敏感)。

3. 分位值:把响应时间从小到大分成一百个等级。

脱离并发来谈性能是没意义的,通常用“吞吐量”和“响应时间”来度量并发和流量:

1. 响应时间:一般响应时间。

2. 吞吐量:当响应时间1s,吞吐量是每秒1次;响应10ms,吞吐量每秒100次。

所以我们设立性能优化目标一般会如下表示:在每秒1万次的请求量下,响应时间99分位值在10ms以下。

高并发下的性能优化思路:

提高系统的处理核心数:

假设系统的处理核心数由一个增加为两个,并且进程也由一个增加到两个,让这两个进程跑在不同的核心上,理论上系统吞吐量增加一倍。

多核心的吞吐量的计算公式与单核心不同:吞吐量 = 并发进程数 / 响应时间。

是不是并发进程数越多,吞吐量越大?NO,并发进程增加,并行的任务对系统资源的争抢越严重,超过某个临界点,性能反而下降,这就是性能测试中的拐点模型。

减小单次任务响应时间:

1. CPU密集型:优化程序计算的算法。

2. IO密集型:磁盘IO与网络IO,通过硬件与软件层面来解决。

2. 高可用

可用性的度量指标:

1. MTBF:Mean Time Between Failure 平均故障间隔时间

2. MTTR:Mean Time To Repair 故障的平均恢复时间

Availability = MTBF / ( MTBF + MTTR )

高可用系统设计思路:

主要分为系统设计和系统运维两方面:

1. 系统设计方面

(1)故障转移(failover)

发生failover的节点有两种情况:

  • 在完全对等的节点之间:所有节点都承担读写流量,并且节点中不保存状态,每个节点都可以作为另一个节点的镜像,所以某个节点失败,简单随机访问另一个节点就可以了。

  • 在不对等节点之间,即主备节点:比如我们有一个主节点,多个备用节点(热备:同样在线提供服务;冷备:只用于备份),我们需要在代码中控制如何检测主备机器是否故障以及如何做主备切换。

故障检测机制与主备切换:

  • 故障检测机制:心跳,可以在客户端定期向主节点发送心跳包,也可以从备份节点上定期发送。当一段时间未收到心跳包,就可以认为主节点发生故障,可以触发选主操作。

  • 选主:选主结果需要在多个备份节点上达成一致,一般会使用某一种分布式一致性算法,比如Paxos,Raft。

(2)超时控制

高并发系统通常会由许多系统模块组成,他们之间调用最怕的是延迟而非失败,因为失败是瞬间的,可以通过重试解决,而延迟会导致调用方阻塞在这次调用上,使它占用的资源得不到释放。当存在大量这种阻塞请求时,调用方就会因为用尽资源而挂掉。所以我们要做超时控制。

超时的时间设置为多少呢?时间短了造成大量超时错误,时间长了起不了作用影响性能。一般通过收集系统之间的调用日志,统计比如说99%的响应时间是怎样的,再依据这个响应时间来指定超时时间。

(3)降级

保证核心任务稳定而牺牲非核心任务的运行。

比如我们发微博通常会进行反垃圾检测,检测通过了再进行入库。而反垃圾检测比较重的操作,在日常流量下虽然耗时但还能正常响应。但当并发较高的情况下,则可能成为瓶颈,而且它不是发布微博的主体流程,所谓当并发高时,我们可以关闭反垃圾服务检测,保证主流流程更加稳定。

(4)限流

通过对并发的请求进行限速来保护系统。

比如web应用,我限制单机只能处理每秒 1000次请求,超过的部分直接返回错误给客户端。

2. 系统运维方面

(1)灰度发布

一般系统啥时候容易出事?除了超出预期的流量外,就是上线变更阶段了。比如你目前上线了一个新需求,数据库慢查增加了一倍,导致系统请求被拖慢从而产生故障。这时,我们就可以用到灰度发布了。我们可以先将服务部署在一台机器上观察一段时间,如果没啥问题,再发布到所有机器上。 

(2)故障演练

为了了解发生故障时的系统表现,我们可以人为的制造故障来进行观察,当然这样还是有风险的,所以很多有钱的公司都会搭一套和线上部署环境一样的线下系统来进行故障演练,从而避免对线上系统造成影响。

3. 可拓展

可扩展性可讲的太多了,后面我会找个时间单独讲讲,今天先大致讲下思路,其实很简单:拆分。即将一个庞大复杂的系统拆分成一个一个的单独模块,而拆分的维度是根据实际情况来的,比如功能、数据、设备等等。

写个文章真的是耗时间啊,本来晚上还想看看视频休息下的,没想到写完就到了可以直接睡觉的点了,大家晚安。        

欢迎大家关注公众号:程序员进阶之路,里面记录了一个非科班程序员的成长之路

                                                   

发布了114 篇原创文章 · 获赞 199 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/qq_36582604/article/details/104240068