我们核心业务系统的中心服务每天承载着上千万金额、几十万笔的订单量,在数据量高速增长,公司业务节节攀升的客观因素下,以及面对即将到来的6月份世界杯的流量\交易 高峰的压力,核心业务系统性能优化以及重构显得越发重要而又迫在眉睫。
时刻准备着
在进行性能优化之前,我们做了很多的准备工作,包括 压力测试,数据库sql提取,性能监控日志数据,请求量等数据的收集,分析整体的性能瓶颈,请求量的波动特点,数据库负载波动情况。
压力测试,几个部门通力的合作,把系统在极端并发的情况下所表现出来的性能瓶颈收集出来,分析出导致系统最终无法对外提供服务的根本原因,但是这种测试我们并不是非常的专业,人手以及环境种种的限制,根据压力测试所分析出来的结果并不理想,能提供的信息很有限。
收集分析生产环境的应用数据不仅仅让我们对系统的性能有个大概的了解,也可以让我们对优化的效果进行持续的观察,便于进行快速的迭代优化,我们把一些能反映系统性能的数据收集到zabbix上,它能直观的反应出波动情况以及数据的走势情况。如:某几条反馈系统业务量的sql的执行次数,某个对核心服务请求量较大的应用的请求数,或者是应用性能监控日志的输出条数(性能较差的方法会输出一条日志)、系统的平均响应时间...
经过大约2周时间的准备工作,是时候开始下一步行动了......
优化手段
根据之前我们收集的性能数据,整理出来了一些性能较差的方法,针对性的对这些方法来选择优化手段,进行优化方案的制定。具体的优化手段有:
1、单条性能较差sql优化-与DBA沟通是否具有优化空间。
2、减少sql的执行的次数(循环单次改成批量(查,插,更新);能使用缓存的地方加上缓存(主要是一些查询);使用频繁的但变动不频繁的数据,整表放入到缓存中;)
3、调用链优化:同一数据由于方法重用导致的重复多次查询更改为通过参数传递;通过调整代码执行的顺序来快速返回不符合条件的业务调用;不需要进入的业务方法,提前退出,不进入。
4、非强一致性要求的幂等判断去除,更改成性能更高的 memcached 简单幂等的方式。
5、减少悲观锁的使用,改乐观锁并通过重试机制来保证业务正常处理。
6、把需要对数据库轮询的业务异步化。
以上几个手段都是针对服务端的性能优化的手段,几乎每一个我们都有广泛的用到。根据不同的使用场景来针对性的使用优化手段,进行调整。
PS:优化和重构都不能影响正常的业务(保持原业务逻辑),强烈建议通过测试用例来进行回归。
效果跟踪
代码调整之后,我们需要对效果进行持续的跟踪,看看优化的效果是否达到预期,另外谁也不能保证改了之后的性能就一定会比改之前的性能更好,尤其是sql优化,改动之后可能改变了执行计划而性能变的更加糟糕。效果的跟踪就显得非常有必要。
在优化前做的那些准备工作就派上用场了,优化之前收集的数据与优化之后的数据在图表上很直观的可以看出走势情况,同一周同一天同一个时段的 某sql执行次数的对比,请求量的对比,数据库负载的对比,平均响应时间的对比,应用内性能监控的日志条数对比...根据不同的手段来进行一些不同的数据的对比,分析优化后的效果,得出的结论之后再进行下一步的行动。
也许我们本身的系统基础搭建的不错,结构清晰,这个时候,细节才决定成败,这也就是这次性能优化为什么先从应用内部找出那些坏代码的原因。应用内部的代码细节都处理好之后,才能放手从架构上,服务调用上做更加深入的优化。下一季,将着重说说在读写分离、边界缓存 上一些经验及体会。