前几天生产机器上的程序突然挂掉了,排查过后发现是网络监控程序之前的业务代码复杂度过高。所以将代码重新优化了一下,记录下这次代码优化的过程
其实在接手代码的时候也想到过之前代码查询数据库次数过多可能会导致数据库宕机,当时也询问了mentor,但是他表示资源是够用的,因为查询的程序不多,所以当时也就没有深入优化。这次挂掉的直接原因应该是又运行了一段新程序,之前复杂度高的代码弊端也就显现出来了
优化前的解决方案
整体的业务逻辑很简单,整个公司联通的所有无线ap(Access Point,无线接入点)每分钟都会受到拨测进行网络监控,如果有异常情况(比如:一星期内有三条时间ap的负载大于50%)就需要对其信息进行筛选,生成告警事件单,并记录目前还未处理事件的告警次数。这次的业务就是对ap up down事件的处理:ap十分钟内无数据上报即判定为ap down。显示在数据库上就是某台ap超过十分钟没有新的记录生成
之前的解决方案是:
- 取数据计算ap消失时间
- 当ap消失时间恰好符合10min时处理告警逻辑,如存在则生成新的告警事件单
因为数据库是每分钟更新一组最新的ap数据的,所以ap消失时间其实也就等同于数据库中每个ap离最近一次记录相差的分钟数。因此真正需要面对的问题是:如何计算数据库中每个ap离最近一次记录相差的分钟数?
有意思的地方到了,之前的计算方式是枚举出这分钟出现的每个ap,然后查每个ap最近的一条记录,时间的差值就是消失时间。然而这也正是代码复杂度高的原因,数据库总共有数万台ap的数据,每分钟要查数据库数万次,这当然很恐怖
当然也不是不能谅解,这其实是基于代码复用和整体结构所做的妥协,毕竟要考虑重复建单等多种情况,因此必须查到确确实实消失了十分钟的ap都有哪些,一分钟不能多,一分钟不能少
优化后的解决方案
服务器宕机后我又重新思考了之前的方案,发现其实也是可以利用的,关键在于如何准确地找到恰好十分钟无数据上报的ap?
很简单,与其计算每个ap消失的时间,不如计算消失时间恰好为十分钟的ap都有哪些。只需要计算十分钟内和十一分钟内出现的ap,作集合的差运算(NOT IN)即可。因为整个程序是每分钟一直运行的,整个服务是动态的,ap拨测数据上报也是动态的,所以此前消失的ap就不需要管,它终究会再次出现,而如果再次收到这台ap拨测的数据后,整个程序就会重新执行这套逻辑,来检验它未来十分钟会不会消失,会不会down掉。步骤更是只需要简单的一条sql语句即可
思考
这次的经历下来最大的感想首先是要有动态的视角,去体会程序动态化运行的过程所带来的收益,这个收益远远比你想象的大。
其次就是要有钻研精神和成本意识,要尽可能地深入思考哪些可以优化的点,不要因为资源够就暂时不去想、懒得想,因为终有一天资源是会不足的,要确保你写下的代码是牢不可破的,用最小的成本去做最大效益的结果,效率远比堆成本重要得多