互联网应用系统的并发能力是每个技术团队都会关注的焦点,随着业务的发展,用户量的不断增加,对系统会带来越来越大的并发压力。系统的响应速度,稳定性等各项指标都会让我们面临前所未有的挑战,是否能够应付高并发问题是衡量一个互联网业务的核心所在。




测试数据库并发能力mysql mysql并发能力大概多少_mysql并发量是多少


一个大型的网站应用一般都是从最初的小规模网站甚至是单机应用发展而来,当系统的吞吐量越来越大,系统的各种资源占用率会逐渐上升,响应时间也会越来越慢。当超过一定临界值后,系统的吞吐量反而会下降。我们所要做的事情,就是要尽量让系统处于上面所示的舒适区。

当高并发来临时,系统哪些部分会成为系统的瓶颈呢?数据库,网络,IO, 系统资源(如CPU,内存等)都有可能成为系统的瓶颈,在一定既定条件下,它们的性能是有限的,我们所要做的工作,就是针对它们进行系统优化。

一些常用于表示系统并发性能的指标有:

  • 吞吐量( Throughput):,系统在单位时间内处理的信息量,直接反应了系统的负载能力,与请求对CPU的消耗,网络接口,IO等密切相关。吞吐量的几个重要的参数就包括系统的并发数,QPS/TPS, RT等指标。
  • 响应时间(Response Time):系统响应请求的时间。在其它条件既定的情况下,系统处理请求越快,用户得到反馈的时间就越短,单位时间内服务器能够处理请求的数量就会越多,直接反应了系统的快慢。一个游戏的响应时间在100ms, 一个网页,在4s内是可以接收的,否则用户就会选择离开。
  • QPS(Query Rate per Second):每秒响应的请求数:并发数/平均响应时间。如域名系统服务器的机器的性能经常用每秒查询率来衡量。
  • 并发用户数(Concurrency Users):同时承载正常使用系统功能的用户数量。
  • PV:综合浏览量(Page View),即页面浏览量或者点击量,一个访客在24小时内访问的页面数量;
  • TPS(Transaction per Second):每秒事务量,和QPS的区别在于,如对一个页面的一次访问,为一个T,它可能包含多个Q。
  • 带宽:计算带宽大小需关注两个指标,峰值流量和页面的平均大小
  • 峰值每秒请求数(QPS)=(总PV数*80%)/(24小时秒数*20%)。(假设80%的访问量集中在20%的时间,也有其他计算方法,如一天中算8小时)

在系统开发过程中,我们需要设计压力测试用例,模拟高并发场景,从而尽早发现和解决问题:

  • 压力测试:测试能承受的最大并发,测试最大承受的QPS值

什么样的系统算是高并发系统呢?

一个小型网站,比如有10万的用户,10%的日活跃用户,假设每个人平均会发起20次请求,PV约为20万次,按 80%的PV会集中在20%的时间算(也有统计认为一天中有8小时是属于用户比较活跃的时段),峰值QPS=200000*0.8/4*3600=11QPS

假设1个页面请求打到数据库层面会有3个请求,数据库的峰值QPS会在30左右。

我们能想到的经常会遇到高并发场景的是搞双十一活动的各种电商平台如淘宝,京东,以及卖火车票的12306.在峰值期间,可能有上亿的用户可能会在同一时间段发起各种操作请求,前端系统QPS承载能高达百万级,后端对数据的查询QPS可能高达千万级。

为了让系统能够支持足够大的业务量,从前端到后端会采用各种各样的技术(比如前端静态资源的压缩整合,使用CDN,分布式架构,缓存,数据库读写分离等)来满足日益增长的业务需求,每个阶段需要根据实际情况来进行优化,优化的方案也与硬件条件、网络带宽息息相关。

系统的基本软硬件条件,决定了单机性能的天花板。

  1. 计算机的大脑—CPU,在不停的运转中,其内核个数的多少,以及主频频率,直接决定了其并发性能的优劣,比如一个单核的CPU,你如果同时开了多个线程执行任务,实际上其“并发性”也高不起来,CPU还得一个个的处理。如果系统是一个CPU密集型业务,CPU瓶颈随着并发的增加很快就会到来,同时我们还不能设置过多的线程,因为线程的切换也需要成本,反而会降低性能。
  2. 存储系统,计算机平日干的事情,就是不断的读取指令,从各种存储媒介中读取数进行计算,再把数据写入存储系统,核存储媒介打交道的速度,则是从各级缓存—>内存—>硬盘,一级一级往后速度呈数量级降低的,因此,你想要高并发,内存一定不能少了。同时,应用系统如何利用缓存来提升系统并发性能,是一个很关键的功能。
  3. 数据库,IO密集型的应用如现在的各种购物平台,系统最大的瓶颈之一会存在于后台数据库。我们来看一下MySQL的并发性能怎么样,在硬件配置很好的极端情况下(加了各种优化措施,比较适中的单表数据量(单表数据超过100万条,性能将急剧下降),并且可以做到数百个并发),MySQL8的只读QPS能达到百万级别。(https://www.mysql.com/cn/why-mysql/benchmarks/),读写能达到20万QPS。 MySQL集群的情况下,QPS会更上一个台阶。至于实际使用中的QPS到底如何,还得在具体的环境上去测试,硬件配置的影响,网络连接会消耗不少时间,不同范围的查询任务和数据量也会使真实的QPS大打折扣。在数据库已知上限的情况下,就是对业务进行优化了,需要利用合适的策略,契合业务特点,对数据做分库分表,来提升最终业务的性能。
  4. 网络带宽,我们的网卡,百兆,千兆,10GB的带宽。带宽的上限,决定了单位时间内,可以传输的数据量。如果网卡成为了系统瓶颈,我们就得升级网卡,或者扩展系统了。
  5. 系统IO,系统与外部系统打交道的方式,分为同步(阻塞式),异步。异步不需要等待系统完全处理完就可以先返回并继续接收下一个请求。此处就需要根据业务特点进行处理,哪些业务必须使用同步方式,哪些业务可以使用异步方式。


测试数据库并发能力mysql mysql并发能力大概多少_mysql并发能力大概多少_02


对单机性能的提升,可称之为垂直扩展--Scale Up,总而言之,聚焦在两方面:

  • 增强单机硬件性能,如增加CPU核数,升级更好的网卡,升级读写速度更快的硬盘,如SSD,扩充系统内存,扩充硬盘容量。
  • 提升单机架构性能,如使用Cache来减少IO次数,使用异步来增加服务吞吐量,使用无锁数据结构来减少响应时间。

在公司业务发展的初期,业务量还没有到非常大的情况下,通过增强单机硬件性能的方式来提升系统的并发能力会来的最快。

不管是提升单机硬件性能,还是提升单机架构性能,都会遇到天花板。这个时候,我们就需要做分布式设计了,也就是如何把系统做横向扩展—Scale Out。

整体系统的Scale out可以在多个层次上进行(比如反向代理层,服务层,数据层都可以实施水平扩展),在提升并发能力的同时,也能提高系统的可用性。

在云时代,虚拟机已经可以做到动态的Scale in和Scale out,软件系统的设计上也应该适应时代的发展,关键系统也要做到能够按需实现动态的伸缩,可以尽可能充分的利用系统资源。

我们在提高系统并发性能的过程中,系统向分布式演进,有一个需要时刻思考的,就是CAP,无论怎么强调都不为过:

  • C(Consistency)—一致性。
  • A(Availability)—可用性
  • P(Partition tolerance)—分区容错性。

任何一个子系统(模块),当横向扩展为多个时,如果其中有数据的状态信息,就都会存在一致性如何保证的问题。一致性又分为强一致性和弱一致性,不同的业务场景可能会有不同的一致性需求。

幂等性保证--同一请求多次发送,最终处理结果要保持一致。

如何开始?

当让你开始开发一个有高并发需求的系统时,应当如何着手呢(在整体架构层面的思路可以参考:

)

一个比较复杂的架构如下图所示


测试数据库并发能力mysql mysql并发能力大概多少_mysql并发量是多少_03


最开始我们需要清楚要支持的并发数有多少,提前做好规划,再进行分解,对应到前端,后端需要支持的QPS是多少。为了支持高并发,使用到的技术手段主要有:缓存,消息队列,服务池化,异步化处理,模块组件横向扩展。

1. 业务模块拆分,微服务化,横向扩展

  • 引入CDN--内容分发网络(Content Delivery Network),实现动静分离,将一些静态资源存放在靠近用户的地方,提高响应速度。
  • 业务分离,微服务化,减少业务系统耦合,可以分而治之。
  • 业务模块无状态化设计,可以实现模块的动态缩放。

2. 缓存--用空间换时间

  • 客户端:前端浏览器页面缓存(HTTP Header中包含Expires/Cache of Control,Last Modified(304,Server不返回Body,客户端可以继续用Cache,减少流量),ETag))
  • 网络中端:反向代理缓存,缓存命中的话可以减少部分向后台系统发送的请求次数,降低后端系统的压力。
  • 服务端:服务端缓存是三者中最重要的部分,数据库往往是后端并发性的瓶颈,为了改善数据读取的状况,我们在开发过程中,可以在平台侧使用缓存框架(如Java的Ehcache),当缓存框架无法满足系统性能要求时,就需要在应用层开发应用级缓存,如使用Redis(可参考《深入分布式缓存》一书,有更详尽的描述)。

3. 数据库使用优化

  • 读写分离,互联网业务大多是读多写少,使用读写分离的方法,能大幅提高数据库的QPS,如前图,只读的QPS可到读写的5倍。
  • 数据表的精细化设计,分库分表,从而减少单表的数据量,提高读写效率。

4. 其他

  • 异步化处理实现系统模块解耦,提高响应速度。
  • 消息队列实现流量削峰,如非关键业务,可以放入消息队列,慢慢处理。
  • 分层限流,提前拒绝,如在负载均衡层就可以做防止重复请求的判断,提前拒绝。在卖商品的场景下,请求已经超过实际的商品数,也可以直接拒绝请求,这样就可以把打到后端的请求大幅减少。
  • 代码逻辑,关注代码细节实现,代码实现是否合理,是否创建了过多的对象,循环遍历是否高效,缓存使用是否合理,是否重用计算结果等,算法使用是否合理。