目录

如何理解高并发系统

1. 业务分治思想+微服务拆分

2. 数据分治思想+分库分表

3. 读写分离思想+主从分离

4. 池化思想

5. 缓存思想

6. 异步思想+消息队列削锋

7. 服务保护思想:熔断降级

8. 限流思想

9. 扩容思想+切流量

10. 海量数据处理思想 ElasticSearch+Hbase

前提:压力测试确定系统瓶颈

附:接口的常规优化的18个方案


如何理解高并发系统

所谓设计高并发系统,首先保证它整体可用的同时,然后,能够承受很大的流量冲击

要设计高并发的系统,要识别系统的各种瓶颈,如内存不足、磁盘空间不足,连接数不够,网络宽带不够等等,以应对突发的流量洪峰。

1. 业务分治思想+微服务拆分

业务分治思想,就是从业务的维度,分而治之,横向扩展

设计一个高并发系统,我们可以分而治之,横向扩展

不同的业务,流量的规模不一样,需要分开应对。

也就是说,高频业务,需要更多的部署多台服务器,把流量分流开,让每个服务器都承担一部分的并发和流量,提升整体系统的并发能力

业务分治思想之后,就可以进行业务的分开建模,

对应在模块设计、模块架构的维度,可以做微服务拆分,这样就可以达到分摊请求流量的目的,提高了并发能力。

所谓的微服务拆分,其实就是把一个单体的应用,按功能单一性,拆分为多个服务模块。

比如一个电商系统,拆分为用户系统、订单系统、商品系统等等

2. 数据分治思想+分库分表

我们知道数据库连接数是有限的。

当业务量暴增的话,MySQL单机磁盘容量会撑爆

一般情况下,MYSQL的吞吐量为 1000-1500qps

另外,由于innodb的 B+树索引的深度限制,最好是单表在500w记录,性能较佳

所以,在高并发的场景下,大量请求访问数据库,MySQL单机是扛不住的!

高并发场景下,会出现too many connections报错。

所以高并发的系统,需要考虑拆分为多个数据库,来抗住高并发的毒打

而假如你的单表数据量非常大,存储和查询的性能就会遇到瓶颈了,

可以首先做sql调优

但是,如果做了很多优化之后还是无法提升效率的时候,就需要考虑做分表了。

分库分表之后,每个表的数据量少一点,提升SQL查询性能。

当面试官问要求你设计一个高并发系统的时候,一般都要说到分库分表这个点。

3. 读写分离思想+主从分离

通常来说,一台单机的MySQL服务器,

一般情况下,MYSQL的吞吐量为 1000-1500qps

另外,由于innodb的 B+树索引的深度限制,最好是单表在500w记录,性能较佳

所以,单机支撑的请求访问是有限的。

因此你做了分布式部署,部署了多台机器,部署了主数据库、从数据库。

但是,如果双十一搞活动,流量肯定会猛增的。

如果所有的查询请求,都走主库的话,主库肯定扛不住,因为查询请求量是非常非常大的。

因此一般都要求做主从分离,然后实时性要求不高的读请求,都去读从库,写的请求或者实时性要求高的请求,才走主库

这样就很好保护了主库,也提高了系统的吞吐。

当然,如果回答了主从分离,面试官可能扩展开问你主从复制原理,问你主从延迟问题等等,这块大家需要全方位复习好哈。

4. 池化思想

在高并发的场景下,各种连接,都可能成为瓶颈

  • 数据库连接

  • HTTP 连接

  • Redis 连接

  • 反向代理连接

因为连接数是有限的。

如何各种连接瓶颈呢?

  • 方式一: 增大连接数量限制

  • 方式二:池化技术

通过池化技术,调用数据库时,可以会先获取数据库的连接,然后依靠这个连接来查询数据,搞完收工,最后关闭连接,释放资源。

反之,如果不用数据库连接池的话,

每次执行SQL,都要创建连接和销毁连接,这就会导致每个查询请求都变得更慢了,相应的,系统处理用户请求的能力就降低了。

使用数据库连接池,可以避免每次查询都新建连接,减少不必要的资源开销,通过复用连接池,提高系统处理高并发请求的能力

和数据库连接池类似,咱们需要:

  • redis 连接池

  • HTTP连接

  • 反向代理连接池

并且,需要使用http长连接,替代短连接

5. 缓存思想

缓存思想是高并发的一大核心架构方案,

无论是各种中间件内部,还是在cpu的内部,还是操作系统内部、在web应用、客户端浏览器的架构设计过程中,广泛的使用缓存思想和模式。

除了一级缓存,甚至有二级、三级缓存、多级缓存架构。

我们使用缓存,主要是提升系统接口的性能,这样高并发场景,你的系统就可以支持更多的用户同时访问。

web应用中,常用的缓存包括:Redis缓存,JVM本地缓存,nginx本地缓存,memcached、CDN静态资源加速等等。

就拿Redis来说,它单机就能轻轻松松应对几万的并发,你读场景的业务,可以用缓存来抗高并发。

缓存虽然用得爽,但是要注意缓存使用的一些问题

  • 缓存与数据库的一致性问题

  • 缓存雪崩

  • 缓存穿透

  • 缓存击穿

然后拿 CDN来说,也属于缓存思想的一种应用,将静态资源,缓存到离用于最近的CDN机房,加速静态资源访问

商品图片,icon等等静态资源,可以对页面做静态化处理,减少访问服务端的请求

如果用户分布在全国各地,有的在上海,有的在深圳,地域相差很远,网速也各不相同。

为了让用户最快访问到页面,可以使用CDN

CDN可以让用户就近获取所需内容。

什么是CDN?

Content Delivery Network/Content Distribution Network,翻译过来就是内容分发网络,它表示将静态资源分发到位于多个地理位置机房的服务器,可以做到数据就近访问,加速了静态资源的访问速度,因此让系统更好处理正常别的动态请求。

6. 异步思想+消息队列削锋

回忆一下什么是同步,什么是异步呢?

一般情况下,服务与服务之间的调用,是同步的rpc调用

同步调用的特点是:

  • 调用简单

  • 结果直观

  • 但是是阻塞执行,性能低

简单来说,同步rpc 它代表调用方要阻塞等待被调用方法中的逻辑执行完成

这种方式下,当被调用方法响应时间较长时,会造成调用方长久的阻塞,在高并发下会造成整体系统性能下降甚至发生雪崩。

那么,如何提升性能?如何抵御高并发?

就是使用异步调用。

异步调用恰恰相反,调用方不需要等待方法逻辑执行完成就可以返回执行其他的逻辑,在被调用方法执行完毕后再通过回调、事件通知等方式将结果反馈给调用方。

因此,设计一个高并发的系统,需要在恰当的场景使用异步

如何使用异步呢?后端可以借用消息队列实现。

比如在海量秒杀请求过来时,先放到消息队列中,快速响应用户,告诉用户请求正在处理中,这样就可以释放资源来处理更多的请求。

秒杀请求处理完后,通知用户秒杀抢购成功或者失败。

我们搞一些双十一、双十二等运营活动时,需要避免流量暴涨,打垮应用系统的风险

因此一般会引入消息队列,来应对高并发的场景

假设你的应用系统每秒最多可以处理2k个请求,每秒却有5k的请求过来,可以引入消息队列,应用系统每秒从消息队列拉2k请求处理得了。

有些伙伴担心这样可能会出现消息积压的问题:

  • 首先,搞一些运营活动,不会每时每刻都那么多请求过来你的系统(除非有人恶意攻击),高峰期过去后,积压的请求可以慢慢处理;

  • 其次,如果消息队列长度超过最大数量,可以直接抛弃用户请求或跳转到错误页面;

7. 服务保护思想:熔断降级

熔断降级是保护系统的一种手段。也可以理解为一种服务保护的思想

当前互联网系统一般都是分布式部署的。

而分布式系统中偶尔会出现某个基础服务不可用,最终导致整个系统不可用的情况, 这种现象被称为服务雪崩效应

比如分布式调用链路A->B->C....,下图所示:

如果服务C出现问题,比如是因为慢SQL导致调用缓慢,那将导致B也会延迟,从而A也会延迟。

堵住的A请求会消耗占用系统的线程、IO、CPU等资源。

当请求A的服务越来越多,占用计算机的资源也越来越多,最终会导致系统瓶颈出现,造成其他的请求同样不可用,最后导致业务系统崩溃。

为了应对服务雪崩, 常见的做法是熔断和降级

最简单是加开关控制,当下游系统出问题时,开关打开降级,不再调用下游系统。还可以选用开源组件Hystrix来支持。

你要保证设计的系统能应对高并发场景,那肯定要考虑熔断降级逻辑进来。

8. 限流思想

限流也是我们应对高并发的一种保护的思想。

这是一种无奈的处理方式

也是一种兜底的处理方式

理论上,咱们是需要能处理所有的请求

但是,有的时候,资源有限,系统的CPU、网络带宽、内存、线程等资源都是有限的。因此,我们要考虑限流。

只能服务其中的部分请求,只能进行无奈的限流,至少能保证部分用户得到正常的服务

如果你的系统每秒扛住的请求是一千,如果一秒钟来了十万请求呢

换个角度就是说,高并发的时候,流量洪峰来了,超过系统的承载能力,怎么办呢?

这时候,我们可以采取限流方案。就是为了保护系统,多余的请求,直接丢弃。

什么是限流:限流,也称流量控制。

限流是指系统在面临高并发,或者大流量请求的情况下,限制新的请求对系统的访问,从而保证系统的稳定性。

具体怎么做限流呢?

可以使用GuavaRateLimiter单机版限流,也可以使用Redis分布式限流,还可以使用阿里开源组件sentinel限流。

面试的时候,你说到限流这块的话?

面试官很大概率会问你限流的算法,因此,大家在准备面试的时候,需要复习一下这几种经典的限流算法哈

9. 扩容思想+切流量

如果是突发的流量高峰,除了降级、限流保证系统不跨,我们可以采用这两种方案,保证系统尽可能服务用户请求:

  • 扩容:比如增加从库、提升配置的方式,提升系统/组件的流量承载能力。

    比如增加MySQL、Redis从库来处理查询请求。

  • 切流量:服务多机房部署,如果高并发流量来了,把流量从一个机房切换到另一个机房。

10. 海量数据处理思想 ElasticSearch+Hbase

Elasticsearch,大家都使用得比较多了吧,一般搜索功能都会用到它

它是一个分布式、高扩展、高实时的搜索与数据分析引擎,简称为ES

我们在聊高并发,为啥聊到ES呢?

因为ES可以扩容方便,天然支撑高并发。

当数据量大的时候,不用动不动就加机器扩容,分库等等,可以考虑用ES来支持简单的查询搜索、统计类的操作。

以上内容,来自《java高并发核心编程卷1 加强版》

前提:压力测试确定系统瓶颈

设计高并发系统,离不开最重要的一环,就是压力测试

就是在系统上线前,需要对系统进行压力测试,测清楚你的系统支撑的最大并发是多少,确定系统的瓶颈点,让自己心里有底,最好预防措施。

压测完要分析整个调用链路,性能可能出现问题是网络层(如带宽)、Nginx层、服务层、还是数据路缓存等中间件等等。

loadrunner是一款不错的压力测试工具,jmeter则是接口性能测试工具,都可以来做下压测。

附:接口的常规优化的18个方案

设计一个高并发的系统,需要设计接口的性能足够好,这样系统在相同时间,就可以处理更多的请求。

当说到这里的话,可以跟面试官说说接口优化的一些方案了。