开篇明义:最近两年来,我越来越觉得性能优化这个领域是个很无聊的领域。
我认为对两个软件比较性能,好比用重量来衡量飞机的建造进度一样意义不大,总体说来:谁的代码少,那么它的运行速度就会越快。
当然,不少人会骂我片面,那就让我们再精确一点描述“在技术水平相同的情况下,代码越少速度越快”,或者再宽泛一点的描述“一般情况下软件大小与运行速度正相关”。
列出一个场景:甲和乙各写了一个相同功能的软件,如Netty和mina,或者SpringCloud和Dubbo,或者redis和memcache,他们想比较出哪种软件更加优秀。往往他们会这么做:写个死循环,相同功能调用100万次,得出结论:netty优于mina,Dubbo优于SpringCloud,memcache优于redis。
程序员和股票分析师的职业其实是有点类似的,遇到这种情况时,他们总得想方设法给出一些理由:dubbo是二进制对象传输,所以网络消耗优于springCloud,memcache是纯内存操作,所以性能优于redis,jetty的代码结构更简单,所以优于以容器为基础的Tomcat......还有一派程序员,会将原因归结到算法上,例如:因为netty使用了基于事件的Nio算法,因此性能会优于使用了Bio的通讯框架,或者归结于先进先出、分布式调用、分库分表等等
但假设两款软件的程序员都到达了顶尖水平,都能轻轻松松解决:IO阻塞、锁等待、流量分发、自动扩容、自动调度 等问题。性能调优最终就是在比较谁家的代码更少,和用重量来衡量飞机建造进度无异。
-----------------------------------------------------------------------------------------------------------------
顺带,介绍一下我的性能调优经验。
一、明确性能指标。
根据业务需求,明确性能指标。性能指标有关键的几种:
1、系统处理能力TPS。即串行情况下,单进程或者单线程每秒处理事务数量。经验而言,单进程带数据库操作150TPS、单进程无数据库操作400TPS已经足够使用。
此时,如果有人提出了3000TPS的需求,这个指标明显是偏高的,过高的TPS有如下问题:无法实现、性价比、可扩展性
因此必须设置好性能指标要求。一般系统而言单进程100TPS已经可以交付生产使用,而优化至单进程200TPS已经是一个较好的系统了。
有人问性能极限是多少呢?我见过单进程3000TPS的系统,见过分布式架构30000TPS的系统,也听闻过单进程100000TPS的系统但是可惜没见过。性能就是计算能力的合理分配,是永无上限的。
2、并发能力。在同等TPS下,系统并行处理业务的能力。有一种场景,串行来10000个用户,可能1秒钟就可以处理完成,如果换成并行,处理时间就会暴增。这往往是由于关键资源争用的影响,如磁盘IO、带宽、数据库锁、进程关键变量等。
如果并发能力上不去,往往会导致:堆再多的机器,遇到活动、大促也会死机。
在这个层面需要合理评估用户并发数量,根据业务需求评估活动参与人数,评估瞬间并发量,切记常规架构单进程扛不过1000并发。当然,有那种单机50W并发的系统,研究性质居多,商业可用性质少。
很多小白其实解决的是这个层面的问题,通过缓存、分布式锁、降低数据库隔离级别、更换算法,进而提升并发能力。
之所以将系统处理能力和并发能力分开,是因为两者的性质不同:
系统处理能力的关键在于删除无用代码,如for改if,函数调用改宏代码块,运行时加载改启动时加载等等
并发能力提升的关键在于解决资源争用,如增加redis缓存,用分布式锁代替数据库锁,表锁优化为行锁,压缩IO提升带宽使用率等。
性能优化指标需要在性能优化前明确提出,其过程如下:1、通过负载测试出最高TPS,2、获得最高TPS位置的峰值并发数,3、制定优化指标:TPS优化提升比例、并发数提升比例。一般提升1.2至1.5倍即可。
二、性能优化
阿姆达尔定律:系统中对某一部件采用更快执行方式所能获得的系统性能改进程度,取决于这种执行方式被使用的频率,或所占总执行时间的比例
性能优化的核心问题在于寻找瓶颈点:找到耗时最久的代码。
不仅是TPS和并发数,都可以通过找到瓶颈点并解决来提升。
寻找瓶颈点的方法和手段有很多,如埋点、计时等等。在JAVA里工具太多了,JProfile,JConsole,JVisualVM等等,一些行家里手也自己写一些性能监测框架如javaAgent等等。但其核心是相同的:通过一段时间的监控,获知哪个方法或者代码块消耗了最多的资源。然后分析这些资源是否有必要:
如果想提升TPS,就删代码,代码越少速度越快。
如果想提升并发数,就增加争用资源,或者将争用资源替换为不需争用的资源。
通过这种方式,可以轻松满足需求,将单进程的TPS和并发数都提升至目标水平。
三、分布式系统架构优化
单进程系统优化至极限,往往还是不满足业务需求,例如单进程极限400TPS并发1000,已经优化至极限,但是业务需求30000TPS,并发15000。
这就要求在架构上不能有热点资源,高可用、横向伸缩性强。例如:业务系统隔离,数据库拆分、微服务化等。
具体说来:
1、业务系统隔离:将无关系统拆分,登陆系统、会员系统、商品系统、库存系统、营销系统、订单系统、支付系统、物流系统、配送系统、仓储系统、财务系统等等。无关的业务进行拆分,各自系统独立运行
2、数据库拆分:横向拆分或者纵向拆分
根据业务线拆分数据库、如实物、虚拟、投资、电器、食品、、、、、、
根据日期拆分数据库、月份、年度、周
根据用户ID拆分订单库,
3、微服务化:订单服务独立、商品服务独立等等
4、异步处理:将同步请求转化为异步请求
5、。。。。。。
但此方案成本巨大,如果是2000TPS,1000并发,0.5s的响应速度,还用不着这么高级的东西。
如果要求是30000TPS,6000并发,0.2s的平均响应速度,就需要这么去优化架构了。
--------------------------------------------------------------------------------------
1、确定目标
2、单进程内优化TPS和并发
3、业务发展至2000TPS以上,考虑架构级别优化
--------------------------------------------------------------------------------------
好久不写技术贴了,需要加强逻辑顺序。
但(假设不同架构的实现者水平都已达到顶尖,不考虑IO阻塞或者锁等待等可解决问题)核心原因在于:代码越少,速度越快。
如果你不认同这点,说明你还没能“轻轻松松解决IO阻塞或者锁等待等可解决问题”,所以觉得这东西有价值。