其实这篇文章,我也不知道用什么标题为好。只是对今天发生的一个案例的思考。
今天是6号,是电信每个新帐期收费的第1天(可能各地有所差异)。某个省电信的收费系统Oracle数据库不堪压力,前台已经不能正常进行收费。而我登上数据库主机时,发现CPU使用率已经达到100%,90%以上的CPU使用率是user模式。这个主机有40个CPU(按逻辑CPU算是80个),而运行队列一直在130以上。
由于我之前没有接触过这套系统,对系统的能力,平时系统的状况都不是很了解。没有发现明显消耗CPU的进程,检查等待事件、以及使用statspack做了个10分钟左右的报告,没有发现特别的异常。唯一的异常是,活动会话太多。
为了解决此问题,客户立即给主机增加了16个CPU(这些CPU本来就在主机上,只是没有划给系统使用),同时重启了应用中间件。这个问题就这样暂时解决了,“火被扑灭了”。
下面分析一下今天这个问题:
大家应该都会有一个共识,应用服务器是很容易水平(横向)扩展的,一台应用服务器不够,可以再增加一台,对于很多应用,应用服务器几乎具有无限制的水平扩展能力。所以一个系统,其甁颈往往出现在数据库。RAC数据库几乎不能够线性扩展,比如两个节点的RAC,其处理能力达到单个节点库的1.6倍已经算是不错了。同时数据库往往受限于IO子系统的能力极限,扩展能力有限。因此,通过增加应用服务器,应用服务器可以接受无限制的请求,但是数据库的处理能力则是有限制的。
回到今天这个问题上,由于今天是业务高峰期,数据库接收到大量来自于应用服务器的请求,达到了某一个临界值以后,系统资源效率下降,比如,IOPS达到一定程度,IO响应时间大幅下降(当然这个系统IO子系统还没表现明显的瓶颈),CPU效率也会下降,同一个事务,以前只需要消耗CPU时间1s的,现在可能需要1.1s,一些等待也会加剧。这样应用服务器的请求队列越来越长,导致数据库的请求也越来越多,活动会话数越来越高。数据库处理的速度已经跟不上请求的速度了。CPU也就长时间保持在100%的使用率,也不足为奇了。
重启应用中间件,就强制中止了所有的请求,消除了排队,避免了给数据库增加更多的压力。重启应用中间件以及增加CPU(增加处理能力)之后,系统就恢复了正常。不过之后一段时间的观察,CPU使用率按之前40个CPU折算,也是在85%左右,也是一个比较高的值。
经过后面一段时间分析,数据库中也存在一些性能问题,存在着较大的优化余地。但是,对于这样一个成熟的庞大的系统来说,不要期望像像网上很多文章介绍的那样,优化极个别的SQL就能解决问题。存在性能不够优化的SQL很多(注意这里说的不够优化,并不是说存在严重的性能问题),并且反映出来的问题很多,涉及面相当广,比如有些表的统计信息缺失,有些SQL写法有问题,有些是索引使用不够合理,执行计划经常变动,不够稳定、有些表有碎片等等。解决这样的系统的性能问题,非一日之功。
所以今天对这个案例,让我思考的是另一方面,对于容量规划。某些系统,像电信的收费(销帐)系统,在业务高峰期,其交易量可以达到平时交易量的2-4倍(只是个粗略估计)。对于这样的系统,我们是不是应该让系统保证足够的处理能力?特别是CPU以及IO子系统能力。对于RAC数据库来说,对每个节点,是不是应该让系统足够在另一个节点DOWN掉的情况下能够支持所有的业务量,如果不能,那么RAC的高可用性就不能得到保证,一个节点DOWN掉以后,其他节点,如果不能承受DOWN掉节点转移过来的压力,也将会不堪重负而垮掉。
同时随着业务量的增加和数据量的增长,系统的压力也会越来越大。因此容量规划也需要考虑这个因素。
对于今天这样的一个系统,如果需要系统能够支撑业务高峰期的压力,通过优化系统,使之在业务低谷期,CPU的利用率应该控制在30%以下,否则今天这样的事情难免会重演。
一篇杂乱的文章,没有详细讨论容量规划,这是一个很大的话题,欢迎讨论。
会不会是并行进程导致?检查下表和索引的并行度?出帐时有可能会出现并行建表或建索引的情况,建好后却忘了将并行属性去掉
[回复]
老熊 回复:
5月 7th, 2009 at 9:17 上午
当时没有这样的情况发生。并且,如果真是并行引起的,那么重启应用后,系统也会再次出现问题。
[回复]
关注你的blog很久了,今天冒个泡,:)
你说的不会是5.1 SZ的库吧
[回复]
老熊 回复:
5月 7th, 2009 at 7:48 下午
感谢你的支持。
文中提到的不是那个库,呵呵。
[回复]
国内的系统普遍设计的比较垃圾。老讲究时髦的技术,结果搞得乱起八糟,上次去移动办业务看他们那的系统,我都快崩溃了。
刚毕业那阵在一家外包公司工作,做日本人的证券系统,当时是工商银行在香港上市,导致系统瘫痪。然后日本人系统性能目标是香港系统的10倍。
设计很重要啊
[回复]
老熊 回复:
5月 8th, 2009 at 10:59 上午
目前国内的现状是,一个项目组(这里指企业应用,其他领域不清楚)中,水平高的只是那么几个人,其他的人可以说一般。系统在开始的时候,系统还比较良好。进入维护期以后,东修西补,同时一些新的需求加上去,应用就越来越烂。而同时数据库这一块,往往是遇到问题才进行处理,久而久之就积累了很多的问题。这些问题单个来看可能不算严重,但是很多问题积累在一起就严重了,并且也不容易解决。
[回复]
恩,很大一个原因是国内对于技术的不重视,没有老程序员,国外的系统架构师技术是非常棒的。
国内整体环境不行啊。
[回复]
老熊 回复:
5月 8th, 2009 at 4:44 下午
当然这些在这里没法讨论,也不是我所能讨论的,呵呵。
[回复]
我们是社会主义初级阶段,慢慢熬吧
[回复]
目前写程序的人不注意性能(或者不熟悉这方面),
只关心功能是否能够实现就完了.没有把功能和
性能结合起来,肯定会出现这方面的问题.
[回复]
老熊 回复:
5月 11th, 2009 at 3:07 下午
有的时候为了赶进度吧,不得不应付了事。
[回复]
可能我依然是理论派,我不认为“RAC数据库几乎不能够线性扩展”,主要还是看应用吧。
OLTP在网格环境下,增加节点必然可以提高容量,但是集群交换的量可能也大了,延迟时间可能也大了。
调优的东西,没有过多的经验,也不敢乱说。倒是觉得这个案例里加CPU的做法还真是个“看山还是山,看水还是水”的做法。
[回复]
老熊 回复:
5月 13th, 2009 at 12:53 下午
这个案例里面,我个人认为增加CPU和重启应用都起了作用。由于没有像latch free这样串行化的等待出现,所以加了CPU,缓减了高负载下CPU不足的问题。当时要去搞SQL优化不,不太现实。机器上有那些CPU,拿来就用了。当然这只是解决当时业务量过大,负载过高的问题,根本的解决办法还是要优化系统。
“RAC数据库几乎不能够线性扩展”,就算是从理论上说,要在RAC中实现线性扩展是很难的。就算“接近”线性扩展,那也可能只是极少数应用。比如数据量小得可以在内存中装下、绝大部分是查询,很少更新,这样的应用,现实中太少。
[回复]
我个人认为对于OLTP而言,RAC要想实现线性扩展,还是得在应用上想办法,即尽量在应用上分离,不同的应用/不同的模块访问不同的节点(比如说以service来分割节点,不同的应用/不同的模块访问不同的service)。但是这样也会有问题,每加一个节点就得改应用。
[回复]
老熊 回复:
5月 13th, 2009 at 7:50 下午
如果这样,实际上并不是使用RAC的扩展性了,而只是利用RAC的高可用性而已了。
[回复]
目前RAC对应用的层次分离是很敏感的,
有些类型的应用在RAC上跑效果不是很
理想的.一般都需要做改变.
[回复]
老熊 回复:
5月 15th, 2009 at 1:03 下午
是的,应用本来就需要做一些调整。不过,部署RAC,要看其目的,到底是其高可用性更重要,还是可伸缩更重要。
[回复]