高并发系统相关概念介绍

2019-10-28  本文已影响0人  兮兮码字的地方

高并发,是指运用设计手段让系统能够处理更多的用户并发请求,也就是承担更大的流量。一般衡量并发大小的指标有qps,tps。

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

高性能、高可用、可扩展

性能反应了系统的使用体验,通常以响应时间来衡量。

可用性则表示系统可以正常服务用户的时间。一个可以做到全年不停机、无故障,一个隔三差五宕机维护的系统,很显然前者更受用户喜爱。

扩展性是指系统在短时间内迅速完成扩容的能力,以更加平稳地承担峰值流量。


一,高性能

性能优化原则

首先,性能优化一定不能盲目,一定是问题导向的。不能为了优化而优化。

其次,性能优化也遵循“八二原则”,即你可以用 20% 的精力解决 80% 的性能问题。所以我们在优化过程中一定要抓住主要矛盾,优先优化主要的性能瓶颈点。

最后,性能优化的过程是持续的。

性能的度量指标

平均值

平均值是把某段时间所有请求的响应时间数据相加,再除以总请求数。

最大值

这个更好理解,就是这段时间内所有请求响应时间最长的值,但它的问题又在于过于敏感了。

分位值

分位值有很多种,比如 90 分位、95 分位、75 分位。以 90 分位为例,我们把这段时间请求的响应时间从小到大排序,假如一共有 100 个请求,那么排在第 90 位的响应时间就是 90 分位值。分位值排除了偶发极慢请求对于数据的影响,能够很好地反应这段时间的性能情况,分位值越大,对于慢请求的影响就越敏感。

分位值是最适合作为时间段内,响应时间统计值来使用的,在实际工作中也应用最多。除此之外,平均值也可以作为一个参考值来使用

从用户使用体验的角度来看,200ms 是第一个分界点:接口的响应时间在 200ms 之内,用户是感觉不到延迟的,就像是瞬时发生的一样。而 1s 是另外一个分界点:接口的响应时间在 1s 之内时,虽然用户可以感受到一些延迟,但却是可以接受的,超过 1s 之后用户就会有明显等待的感觉。

高并发下的性能优化

1. 提高系统的处理核心数

CPU 密集型系统中,需要处理大量的 CPU 运算,那么选用更高效的算法或者减少运算次数就是这类系统重要的优化手段。

2. 减少单次任务响应时间

IO 密集型系统指的是系统的大部分操作是在等待 IO 完成,这里 IO 指的是磁盘 IO 和网络 IO。我们熟知的系统大部分都属于 IO 密集型,比如数据库系统、缓存系统、Web 系统。


二,高可用

可用性的度量

可用性是一个抽象的概念,如何来度量它呢,与之相关的概念是:MTBF 和 MTTR。

MTBF(Mean Time Between Failure)是平均故障间隔的意思,代表两次故障的间隔时间,也就是系统正常运转的平均时间。这个时间越长,系统稳定性越高。

MTTR(Mean Time To Repair)表示故障的平均恢复时间,也可以理解为平均故障时间。这个值越小,故障对于用户的影响越小。

可用性与 MTBF 和 MTTR 的值息息相关,我们可以用下面的公式表示它们之间的关系:

Availability = MTBF / (MTBF + MTTR)

高可用系统设计的思路

1. 系统设计

failover(故障转移)、超时控制以及降级和限流。

failover 有两种

1. 是在完全对等的节点之间做 failover。

2. 是在不对等的节点之间,即系统中存在主节点也存在备节点。

超时控制实际上就是不让请求一直保持,而是在经过一定时间之后让请求失败,释放资源给接下来的请求使用。这对于用户来说是有损的,但是却是必要的,因为它牺牲了少量的请求却保证了整体系统的可用性。

降级是为了保证核心服务的稳定而牺牲非核心服务的做法。比方说我们发一条微博会先经过反垃圾服务检测,检测内容是否是广告,通过后才会完成诸如写数据库等逻辑。

限流完全是另外一种思路,它通过对并发的请求进行限速来保护系统。

比如对于 Web 应用,我限制单机只能处理每秒 1000 次的请求,超过的部分直接返回错误给客户端。虽然这种做法损害了用户的使用体验,但是它是在极端并发下的无奈之举,是短暂的行为,因此是可以接受的。

2. .系统运维

灰度发布、故障演练

灰度发布指的是系统的变更不是一次性地推到线上的,而是按照一定比例逐步推进的。一般情况下,灰度发布是以机器维度进行的。比方说,我们先在 10% 的机器上进行变更,同时观察 Dashboard 上的系统性能指标以及错误日志。如果运行了一段时间之后系统指标比较平稳并且没有出现大量的错误日志,那么再推动全量变更。

故障演练指的是对系统进行一些破坏性的手段,观察在出现局部故障时,整体的系统表现是怎样的,从而发现系统中存在的,潜在的可用性问题。

ps:可用性和性能有时候是需要做取舍的,但如何取舍就要视不同的系统而定,不能一概而论了。


三,可扩展

高可扩展性表示可以通过增加机器的方式来线性提高系统的处理能力,从而承担更高的流量和并发。

提升扩展性是一个复杂问题,例如,可以在单机系统中通过增加处理核心的方式,来增加系统的并行处理能力,但这个方式并不总生效。因为当并行的任务数较多时,系统会因为争抢资源而达到性能上的拐点,系统处理能力不升反降。

需要站在整体架构的角度,来考虑系统的扩展性 。数据库、缓存、依赖的第三方、负载均衡、交换机带宽等等都是系统扩展时需要考虑的因素。要知道系统并发到了某一个量级之后,哪一个因素会成为我们的瓶颈点,从而针对性地进行扩展。

高可扩展性的设计思路

拆分是提升系统扩展性最重要的一个思路,它会把庞杂的系统拆分成独立的,有单一职责的模块。将复杂的问题简单化。

1.存储层的拆分

业务维度的数据库拆分

例如一个简单的社区系统按照业务拆分之后,分为,用户库、内容库、评论库、点赞库和关系库。

按照业务拆分之后,可能单一的业务数据库在容量和并发请求量上仍然会超过单机的限制。这时,我们就需要针对数据库做第二次拆分。

数据维度的数据库拆分

这次拆分是按照数据特征做水平的拆分,比如说我们可以给用户库增加两个节点,然后按照某些算法将用户的数据拆分到这三个库里面,(也就是数据库分库分表)

做了水平的数据库拆分之后,我们就可以让数据库突破单机的限制了。但这里要注意,我们不能随意地增加节点,因为一旦增加节点就需要手动地迁移数据,成本还是很高的。

当数据库按照业务和数据维度拆分之后,我们尽量不要使用事务。因为当一个事务中同时更新不同的数据库时,需要使用二阶段提交,来协调所有数据库数据一致性。这个协调的成本会随着资源的扩展不断升高,最终达到无法承受的程度

2. 业务层的拆分

一般会从三个维度考虑业务层的拆分方案,它们分别是:业务纬度,重要性纬度和请求来源纬度。

首先,可以把相同业务的服务拆分成单独的业务池,比方说上面的社区系统中,我们可以按照业务的维度拆分成用户池、内容池、关系池、评论池、点赞池和搜索池。

除此之外,可以根据业务接口的重要程度,把业务分为核心池和非核心池。打个比方,就关系池而言,关注、取消关注接口相对重要一些,可以放在核心池里面;拉黑和取消拉黑的操作就相对不那么重要,可以放在非核心池里面。这样,我们可以优先保证核心池的性能,当整体流量上升时优先扩容核心池,降级部分非核心池的接口,从而保证整体系统的稳定性。

最后,还可以根据接入客户端类型的不同做业务池的拆分。比如说,服务于客户端接口的业务可以定义为外网池,服务于小程序或者 HTML5 页面的业务可以定义为 H5 池,服务于内部其它部门的业务可以定义为内网池,等等。

ps:拆分后,系统可扩展性增强,但同时也加大了运维难度。

上一篇下一篇

猜你喜欢

热点阅读