Database Connection Pool
RWP团队谈性能优化之大开眼界篇(一)连接池策略
开始的时候让大家思考 到数据库服务器的连接数,您觉得应该跟什么有关?
1. 系统需要支持的最大并发用户数
2. 硬件,数据库服务器上的CPU数量
3. 硬件,数据库服务器上的内存大小
4. 只要设的足够大,应用不报错就行
然后进行了demo。demo中用到一台数据库服务器,两台应用服务器。数据库服务器是Exadata X8-2的一个计算节点(48 CPU Core),应用服务器是Exadata X8-2的两个计算节点,都坐落在美国的一个数据中心里。 开始demo,连接池的最小值是288,最大值是6000。28800个Java Thread 每10000ms向数据库里发送一个request,系统非常闲,CPU使用率不到10%。 将Think Time由10000改为5000,即每个Java Thread每隔5000ms向数据库里发送一个Request,工作负载翻倍。 工作负载翻倍之后,响应时间不变,TPS翻倍,系统的扩展性完美。 进一步减少Think Time,将Think Time由5000改为2500。到数据库的连接从200多激增到了将近5000,连接风暴发生了。过程中响应时间突然变慢好几百倍,TPS没有马上翻倍。过了一会儿,响应时间似乎又稳定下来了,TPS也基本翻倍,基本线性增长了。
连接风暴发生的根本原因,是连接池配置问题。连接池最大值是6000,最小值是288,当连接不够用的时候,连接池就会增长,在demo里面,是不但增长而且急剧的增长了。
Demo里面发生连接风暴的时候,数据库服务上的CPU使用率都不到20%。就是说,即使系统很闲的时候,动态连接池策略也会有连接风暴的风险。动态连接池,是指连接池的最大值不等于最小值。当最大值与最小值相差很大,比如相差几千的时候,连接风暴的风险尤其大。 将Think Time由2500改为1200的时候,再一次经历了连接风暴,到数据库的连接从将近5000增加到了6000。 Think Time=300的时候,响应时间时间非常不稳定,通常在几百毫秒,TPS也非常不稳定,相比Think Time=600/1200的时候,TPS根本就没有升高,反而整体还低了一些,数据库里面的活跃会话数基本在5000以上,数据库里有大量的等待事件,主要是latch: cache buffers chains, buffer busy waits,enq: TX – index contention 这些Concurrency类型的等待事件。
解决问题的办法可以是自下而上的,去分别研究每个等待事件,调参数,trace等等。也可以是自上而下的,跳出细节,考虑一下为什么会有这些等待事件。
关系型数据库都是要做到ACID的。为了ACID,数据库里面肯定有各种串行的机制,比如latch,lock等等,不然比如不同进程同时都去修改同一个buffer,结果就都乱套了。所以等待事件是表象。 真正的原因是连接数太多了,6000个连接,去抢48个CPU资源,以及系统里的其他资源。可以看到等待事件都是Concurrency类型的,那如果减少连接数,系统的整体性能会不会变好?
然后在demo里,仅仅做了一个改变,将连接池的最大值,从6000改成了288。结果是,响应时间减少了十几倍,且非常稳定,TPS大幅升高,且非常稳定。数据库服务器上的CPU使用率非常稳定,整体还下降了。数据库里之前的大量的等待事件都不见了。
有一种消除大量等待事件的方法,叫 减少连接数。 Oracle数据库是process-based architecture。最常见的用dedicated server方式连接,意味着,对于每一个连接,在数据库服务器端有一个进程给这个连接服务。 过多的连接,意味着过多的进程,但是并不意味着更高的TPS。Demo里面,使用288个连接的时候,与使用6000个连接相比,数据库服务器使用了更少的CPU,却使得响应时间变短了,TPS升高了。 CPU的使用效率才是关键。连接数过多会导致CPU cache的命中率下降,从而使得CPU使用效率下降。连接数过多时,latch的spin机制可能导致更多的空耗的CPU,从而使得CPU使用效率下降。 然后在demo里继续减少Think Time。Think Time=0的话,就是每个Java Thread不停的向数据库里发送请求。 在Think Time=300的时候,数据库的处理能力已经达到上限了。数据库服务器的CPU core数是没变的,连接数也是没变的,所以再增加工作负载,数据库处理每个请求的时间还是不会变的,TPS也不会变,但是响应时间增加了,都是增加在了排队等待连接的时间。 不管Think Time是150还是0,结果都是可以预期的,TPS基本不会变,数据库服务器CPU基本不会变,数据库里不会出现大量的concurrency类型的等待事件,响应时间会比之前长,长多少取决于排队拿连接的时间,Think Time越小,响应时间就会越长
合适的连接池策略,能够保证系统的平稳运行。不管工作负载怎么增加,TPS都不会降低,数据库服务器的CPU也不会升高,数据库里也不会出现因大量竞争而导致的等待事件。只是响应时间会变长,因为需要排更长的队等待数据库连接。 如果此时对响应时间不满意,怎么办? 该扩容啦。48个CPU core,运算能力摆在那,能干多少活儿也就确定啦。 总结 建议使用静态连接池,就是说,连接池的最大值等于最小值,这样可以避免连接风暴的风险。 建议连接池的最大值等于最小值等于数据库服务器CPU core数的1-10倍。CPU core,指的是物理的core数,而不是超线程之后的。1-10倍只是一个参考值,具体适合的数值与具体的工作负载有关,需要测试才能确定。如果工作负载做的I/O相对多一些,则可能更接近于10倍是适合的数值,如果工作负载做运算耗CPU相对更多一些,则可能更接近于1倍是适合的数值。 如果连接池策略合适,系统其他方面也已经很优化了,SLA还是不能满足要求,怎么办? 扩容。
Comments
Post a Comment