你开发的系统到底可以支撑多少并发访问?( 三 )


文章插图
 
如果这篇文章说不清epoll的本质 , 那就过来掐死我吧!
这篇文章把epoll的原理讲得比较透 , nginx、tomcat、redis、kafka等等所有高性能的中间件的底层都是使用epoll 。
此处的基准测试是个很重要的环节 , 我们网上能够看到的很多文章所谓的高并发高性能 , 都是一些理论值 , 或者说是推测出来的一个量级 , 实际值跟网络情况服务器情况的不同会有较大的差别 , 做好基准测试是我们做性能优化非常重要的一环 , 而基准测试的核心就是在一个简单的配置环境下发现核心性能点的瓶颈 , 例如如果一台服务器装了个nginx , 发现压测结果是并发1万 , 那就是由于某些原因完全没测出来瓶颈 , 需要从CPU、网络等角度来排查哪一环出现了问题 。很多时候我们可以使用压测工具得到一个数值 , 这不是关键点 , 关键点在于这个值对不对 , 到底瓶颈在哪 , 是CPU还是网络 , 是内存还是硬盘 。
应用问题?确认了网络编程在epoll配置下普通服务器都可以达到10万并发级别 , 现在来看看十万并发的请求到了应用代码执行层面会不会出现问题 。如果抛去数据库的查询速度 , 单纯在代码执行和内存访问 , 基本都是在纳秒级别 , 下图可以看到各硬件访问的速度 , 单纯执行1000行代码还是处于微妙级别 , 访问1000次内存 , 也只是100微秒即0.1毫秒 , 所以如果没有高并发下的锁竞争 , 仅是代码执行也很少会出现高CPU的情况 , 除非是递归调用等特殊场景 。

你开发的系统到底可以支撑多少并发访问?

文章插图
 
数据库问题?分析了网络层瓶颈在单机十万 , 应用层基本不会存在瓶颈 , 那么下一层就是数据库查询了 , 也就是说 , 当十万并发请求进来的时候 , 基本上在网络处理和程序执行上不会存在多少损耗 , 会直接将流量打到数据库上 , 那么此时就需要了解数据库的瓶颈点和极限值了 。数据库的知识点就比较多了 , 因为经过这么多年的发展 , 数据库做了N多优化 , 而且存储也是一个系统的重中之重 , 基本上所有的优化都是从数据库开始的 。可以先从数据库的简单原理了解下数据库的性能到底怎么样 。
你开发的系统到底可以支撑多少并发访问?

文章插图
 
上图以mysql为例列出了请求从网络到执行再到持久化四个大过程的基本实现原理 。第一步是connection pool来处理连接 , 认证等工作;第二步是解析sql、优化sql和查询mysql库级别缓存;第三步进入存储引擎处理 , mysql目前默认的存储引擎是innodb;第四步就是磁盘访问了 。根据上述的网络处理分析 , 第一步基本不会存在瓶颈 。第二步都是代码执行的内存访问 , 也不太会成为瓶颈 。第三步是引擎执行 , innodb支持三种行锁 , 但是查询时mvcc不加锁 , 并且当数据库记录数量不是特别大(百万或千万级)时 , 数据的定为都是基于内存中的page进行的 , 一般情况下也不会存在瓶颈 , 只有第四步的磁盘访问会成为瓶颈 。
为了保证数据稳定持久化 , 一定是要将数据存储在磁盘上的 , 因为计算机一共就有两类存储 , 磁盘和内存 , 内存是基于电容的 , 原理就是通电后通过01信号来表示数据 , 而磁盘是通过磁极变化来记录表示01数据 , 通电改变磁场写入数据 , 断电后不会发生改变 。所以要想让数据持久保留 , 必须用磁盘 。当然磁盘有很多种 , 普通的机械硬盘 , SSD硬盘 , 磁带等等 。因为内存是靠电来表示数据 , 所以足够快 , 但是磁盘中 , 当磁头扫过盘面 , 通过感应电流就可以识别出不同状态 , 即读取数据;增强磁头的磁性 , 可以改变盘面记录单元的状态 , 实现写入数据 。此时带着磁头的机械臂摆动就会成为访问瓶颈 , 由此可见 , 数据库的第一大瓶颈就是磁盘的写入和读取 。
根据上面列出的硬件访问速度 , 磁盘访问在10ms左右 , 因为机械臂的移动速度在7ms左右 。如果每次数据库查询都需要10ms , 那么此时我们就可以算算 , 数据库CPU此时除了网络处理和数据查找(定位磁盘位置)以外 , 剩余的执行时间都是等待磁盘IO , 可以适当增加线程数并行执行网络处理和数据查找 , 并行等待磁盘IO , 即提高数据库连接数 , 传导到应用层面即为增加请求的连接数 。此时通过增加应用连接数来提高并发能力 , 可以快速将数据库的瓶颈突破到磁盘瓶颈 , 按照正常物理机的固态硬盘的速度 , 每秒可以处理116k次16KB数据的随机读 , 即11万并发 , 当然此时数据库基本处于满负荷状态 , 崩溃边缘 , 正常支撑6万以下并发处于合理范围 , 如果将数据库部署到虚拟机上或者低配机上 , 那么并发量会直线下滑 , 我们内部的一个虚拟机作为数据库服务器的基准测试结果惨不忍睹 , 16k随机读的IOPS仅为600 , 即当有600查询请求进来时 , 磁盘IO为100%了 。以上数据均属于内部基准测试得出的结果 , 实际生产环境或其他环境需要根据基准测试和全流程压测的实际值为准 。


推荐阅读