来公司有一年时间了,一直在马不停蹄的做着新的业务,但要想做好新业务就不能过多将时间消耗在其它方面。刚来的半年时间,我们消耗了30%左右的时间在时间系统维护上。我们一边做新业务,一边天天需要花时间在系统维护上,难免会心力交瘁,前半年由于刚来公司,需要大量时间熟悉现在系统,分析优点缺点,努力去发现问题,期间有很多想做的事一直没有推进。我前后经过近一年的时间,参与了开发我们组几乎所有核心模块的代码,所以对其中的问题基本把握的比较准确,半年后花了近三个月时间来重构优化系统(当然不是团队停下来专门做重构,只能在新业务中挤时间),小有成果,这里分享很大家:
我先简单介绍下我们主体业务的几个模块以及对应的问题:(有一部分问题是因为数据量大造成的,其余是系统设计问题)
看到上面的问题,可以归纳出,在数据量大的时候,系统的基本功能都不能保证正常运转,那么应对的方案按优先级订为:
功能不能正常运转问题:
先来看个小故事:去年的某月提单高峰日,线上出现用户反馈提单失败,网站响应速度非常慢。因为之前未出现过同类现象,所以我们下意识的认为不应该是程序问题,是否是服务器的问题,但查看服务器的负载并未发现问题,由于半夜都未解决问题,最终我们领导刚准备睡觉最终提起脱了一半的裤子又来到公司与我们一起奋战。后来沟通才得知是一批新的用户使用了系统,他们的特点就是一次性提交的订单数据非常多(一次2000以上)。之前系统由于没有经过大量订单的考验所以没有暴露出问题来,知道情况后经过分析确认是程序面对大量订单时比较脆弱。下面是解决的一些主要问题小集合:
下面的这类查询需求,想必是比较常见的,查询指定范围内的数据,扩展的目的是为了调用方便,容易理解
下面是扩展的方法以及问题描述
我并没有尝试去解决这个表达式的问题,直接改成Contains就解决问题了。
订单达到一定数量时,在更新数据库时会生成大量的SQL语句,容易形成SQL传输的网络堵塞最终产生数据库操作超时(之前提交2000个订单时,单表需要生成2000行SQL),解决方案是按批次来处理,比如500条数据一个批次操作数据库,将大批次改成小批次来处理就不会有问题。
原方案:用户在导入数据的时候,显示一个滚动的图片,但这个滚动的图片不是真正的进度条,用户无法知道导入的进程到底什么时间能够完成。
新方案:
最严重的当数这些与金额相关的数据,由于系统设计的不够严谨,导致金额数据出现负数。为了彻底堵住这个漏洞,我在实体模型上做了霸王条款:
所以我们在设计数据库以及实体模型时,一定要确保数据在可掌控范围内,决不能允许出现错误数据。
比如购买了一个订单,数据是100个,用户可随意使用,使用一个就在订单上记录一个已使用的数据,最终到已使用数据=原订单数量,其中用户如果做退款下线,那么这个已使用数据还需要回补回来。问题有主要有两个:
我个人并不推荐采用这种利用一个数据库字段来记录核心数据的方案,因为它总是基于一个中间状态在做运算,其中只要出现一个错误,后面的运算都会出错,最起码我们应该有数据监控,以确保这个结果值是正常的。
数据一致性问题:
除了从系统角度去发现问题的本质并解决,另外就是采用一种亡羊补牢的方式:数据监控以及数据的自动修复。将核心的业务数据监控起来,当发现有异常时通过一种报警机制通过相关负责人。能够确认的问题可通过一些工具实现数据的自动修改,比如某些服务临时调用失败,我们就可以自动的重新调用直到成功为止。
性能问题:
可采取一些工具或者纯人工记录日志的方式,这里我使用了dottrace,专打出头鸟:
列表页有一个批量的订单,它会包含多个订单,但列表为了显示的统一,给这个批量的订单也会显示它的价格以及状态,它的价格是下面所有子订单的价格总和,订单的状态是下面所有子订单的状态中最小的状态,所以应用了一个递归来查询,非常消耗时间。经常与业务方沟通后,确认这两个我们花了大量去计算的数据对业务方其实并没有什么实质的作用,果断去掉,性能提升感觉是从地狱到了天堂。
总结:我们的目的就是为了用户能够愉快的使用系统,为此我们持续不断的进行重构优化。优化都是相对的,我们不一定要找到最完美的方案,但保证用户体验是最基本的要求。
本文链接:系统优化总结,转载请注明。