高并发系统基础篇

1,528 阅读8分钟

一、通用的设计方案

1、scale-out 横向扩展

分而治之是一种常见的高并发系统设计方法,采用分布式部署的方式把流量分流开,让每个服务器都承担一部分并发和流量。

2、缓存

一般的持久化存储都是使用磁盘作为存储介质的,而普通磁盘数据由机械手臂、磁头、转轴、盘片组成,盘片又分为磁道、柱面和扇区,盘片构造图我放在下面了。

盘片是存储介质,每个盘片被划分为多个同心圆,信息都被存储在同心圆之中,这些同心圆就是磁道。在磁盘工作时盘片是在高速旋转的,机械手臂驱动磁头沿着径向移动,在磁道上读取所需要的数据。我们把磁头寻找信息花费的时间叫做寻道时间。普通磁盘的寻道时间是 10ms 左右,而相比于磁盘寻道花费的时间,CPU 执行指令和内存寻址的时间都是在 ns(纳秒)级别,从千兆网卡上读取数据的时间是在μs(微秒)级别。所以在整个计算机体系中磁盘是最慢的一环,甚至比其它的组件要慢几个数量级。因此我们通常使用以内存作为存储介质的缓存,以此提升性能。

3、 异步

异步也是一种常见的高并发设计方法

二、分层架构

1、MVC分层

整体的系统分成了 Model(模型),View(视图)和 Controller(控制器)三个层次,也就是将用户视图和业务处理隔离开,并且通过控制器连接起来,很好地实现了表现和逻辑的解耦,是一种标准的软件分层架构

2、项目分层

表现层,顾名思义嘛,就是展示数据结果和接受用户指令的,是最靠近用户的一层;逻辑层里面有复杂业务的具体实现;数据访问层则是主要处理和存储之间的交互。我们通常会建立三个目录:Web、Service 和 Dao,它们分别对应了表现层、逻辑层还有数据访问层。

3、 网络分层 OSI TCP/IP

OSI 网络模型,它把整个网络分成了七层,自下而上分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。工作中经常能用到 TCP/IP 协议,它把网络简化成了四层,即链路层、网络层、传输层和应用层。每一层各司其职又互相帮助,网络层负责端到端的寻址和建立连接,传输层负责端到端的数据传输等,同时相邻两层还会有数据的交互。

4、Linux文件系统

在文件系统的最上层是虚拟文件系统(VFS),用来屏蔽不同的文件系统之间的差异,提供统一的系统调用接口。虚拟文件系统的下层是 Ext3、Ext4 等各种文件系统,再向下是为了屏蔽不同硬件设备的实现细节,我们抽象出来的单独的一层——通用块设备层,然后就是不同类型的磁盘了。我们可以看到,某些层次负责的是对下层不同实现的抽象,从而对上层屏蔽实现细节。比方说 VFS 对上层(系统调用层)来说提供了统一的调用接口,同时对下层中不同的文件系统规约了实现模型,当新增一种文件系统实现的时候,只需要按照这种模型来设计,就可以无缝插入到 Linux 文件系统中。

总结:分层的优势与不足

优势:分层的设计可以简化系统设计,让不同的人专注做某一层次的事情;分层之后可以做到很高的复用;分层架构可以让我们更容易做横向扩展

不足:系统不易维护

三、高并发系统的设计目标

1、提升性能

性能度量指标

均值、最值或是分位置。一般常用分位置。我们把这段时间请求的响应时间从小到大排序,假如一共有 100 个请求,那么排在第 90 位的响应时间就是 90 分位值。分位值排除了偶发极慢请求对于数据的影响,能够很好地反应这段时间的性能情况,分位值越大,对于慢请求的影响就越敏感。(小->大) 性能优化的目标时通常会这样表述:在每秒 1 万次的请求量下,响应时间 99 分位值在 10ms 以下。

性能优化方法

(1)增加系统处理核心数

是不是无限制地增加处理核心数就能无限制地提升性能,从而提升系统处理高并发的能力呢?很遗憾,随着并发进程数的增加,并行的任务对于系统资源的争抢也会愈发严重。在某一个临界点上继续增加并发进程数,反而会造成系统性能的下降,这就是性能测试中的拐点模型。 从图中你可以发现,并发用户数处于轻压力区时,响应时间平稳,吞吐量和并发用户数线性相关。而当并发用户数处于重压力区时,系统资源利用率到达极限,吞吐量开始有下降的趋势,响应时间也会略有上升。这个时候,再对系统增加压力,系统就进入拐点区,处于超负荷状态,吞吐量下降,响应时间大幅度上升。

(2)减少单次任务的响应时间

2、高可用

高可用性(High Availability,HA)是你在系统设计时经常会听到的一个名词,它指的是系统具备较高的无故障运行的能力。

例如:Hadoop1.0的NN与Hadoop 2.0的NN。 Hadoop 1.0 中的 NameNode 是单点的,一旦发生故障则整个集群就会不可用;而在 Hadoop2 中提出的 NameNode HA 方案就是同时启动两个 NameNode,一个处于 Active 状态,另一个处于 Standby 状态,两者共享存储,一旦 Active NameNode 发生故障,则可以将 Standby NameNode 切换成 Active 状态继续提供服务,这样就增强了 Hadoop 的持续无故障运行的能力,也就是提升了它的可用性。

(1)可用性的度量标准

MTBF(Mean Time Between Failure)是平均故障间隔的意思,代表两次故障的间隔时间,也就是系统正常运转的平均时间。这个时间越长,系统稳定性越高。MTTR(Mean Time To Repair)表示故障的平均恢复时间,也可以理解为平均故障时间。这个值越小,故障对于用户的影响越小。可用性与 MTBF 和 MTTR 的值息息相关,我们可以用下面的公式表示它们之间的关系:

Availability = MTBF / (MTBF + MTTR)

这个公式计算出的结果是一个比例,而这个比例代表着系统的可用性。一般来说,我们会使用几个九来描述系统的可用性。

(2)高可用的设计思路

故障转移:我们有一个主节点,有多台备用节点,这些备用节点可以是热备(同样在线提供服务的备用节点),也可以是冷备(只作为备份使用),那么我们就需要在代码中控制如何检测主备机器是否故障,以及如何做主备切换。使用最广泛的故障检测机制是“心跳”。你可以在客户端上定期地向主节点发送心跳包,也可以从备份节点上定期发送心跳包。当一段时间内未收到心跳包,就可以认为主节点已经发生故障,可以触发选主的操作。选主的结果需要在多个备份节点上达成一致,所以会使用某一种分布式一致性算法,比方说 Paxos,Raft。

超时控制:复杂的高并发系统通常会有很多的系统模块组成,同时也会依赖很多的组件和服务,比如说缓存组件,队列服务等等。它们之间的调用最怕的就是延迟而非失败,因为失败通常是瞬时的,可以通过重试的方式解决。而一旦调用某一个模块或者服务发生比较大的延迟,调用方就会阻塞在这次调用上,它已经占用的资源得不到释放。当存在大量这种阻塞请求时,调用方就会因为用尽资源而挂掉。

降级、限流

3、易扩展

拆分是提升系统扩展性最重要的一个思路,它会把庞杂的系统拆分成独立的,有单一职责的模块。相对于大系统来说,考虑一个一个小模块的扩展性当然会简单一些。将复杂的问题简单化,这就是我们的思路。

【提示】理论来源:极客时间-高并发系统40问-唐扬