系统性能优化小结

系统性能优化小结

    最近开发过程中,遇到两次性能优化的需求,几番努力完成性能要求,一个因为工作改动量大而没有付诸实践,现小结如下。

场景一

    现状

    对外提供的网络接口,数据库数据都走了redis的缓存,但是在此情况下,仍然请求在10秒多,数据量大的时候需要快20秒,现要求是秒以内的响应速度。

    分析与修改

    首先对各个方法进行响应时间的日志添加,运行几种情况,看看那些方法时间长,主要关注点在I/O,远程请求,数据库操作。经过几轮测试之后,发现主要数据库操作耗时,核对代码发现其实是数据库缓存没有存进去,修改后再次测试,发现还是没有走缓存,核对代码发现其实存进去的key和查询用的key不同,修改后在次测试,发现性能大幅提升,全部走缓存的情况下,基本在800毫秒左右。但是在测试中,发现如果不走缓存的时候,数据量大的时候响应非常慢,初步怀疑是数据库中的增删改操作有问题。核对代码后发现是批量更新的时候是一条一条更新的,每次更新都连接数据库,一旦数据量达到几十条的时候,会很耗时。最后分析需要使用mybatis的动态sql,批量更新,减少数据库操作。修改后确实性能大幅提升。批量更新主要还是使用case when 和for 关键字。

    总结

    现在缓存技术已经普遍使用在软件开发过程中,设置有相同的key值存取是不能出错,否则会造成存取不一致,缓存不起作用;数据库操作,涉及到批量的操作时候,一定要采用批量操作的方式,否则会造成性能下降。

场景二

    现状

    微服务架构,对外的接口服务调用业务服务获取数据库结果,并在接口服务中多线程调用第三方的http请求。目前响应时间较长,大约20秒左右,希望能降低到6秒内。

    分析与修改

    也是对主要方法进行了粗略的浏览,对主要方法添加时间日志,  经过测试发现主要是调用第三方的时候,多次调用导致耗时,之所以多次调用是因为一次调用的时候结果不完整,所以调用了多次。为了保证能拿到完整结果,所以每调用一次之后,当前线程睡眠1秒后再次调用,如此往复最多五次。经过测试发现,大多数情况是第一次或者第二次就能返回结果,直到第三次返回结果的概率较小。经过分析后,得出得方案是,第一次查询,查出一部分结果就返回给用户,然后再查第二次,第二次结果回来后,如果用户需要查看全部结果则展示第二次查询的完整结果。虽然复杂,但是可以很大程度上提升用户体验。但是因为涉及的改动较大,方案被搁置。除此之外还做了一些,小的优化。1.map的初始化容量。从数据库查询的结果要存储在一个map中,查询结果的数量是几千条,这个时候在创建map对象的时候,指定容量以避免多次扩容造成性能损耗;2.缓存时间。对于一些一直不变的大量数据,在缓存中的失效时间设置的需要长一些,以降低数据库查询的次数,整体上减少平均请求时间。建议至少一天;3.缓存穿透。对于一系列相关的缓存,需要将其缓存失效时间设置为阶梯状,最好不要设置为相等的时间,这样子在同时失效时,会造成某一时刻都去查询数据库,性能大幅下降。4.修改线程的休眠时间。上面描述,大部分请求都是在两次请求后就可拿到结果,所以将线程的休眠时间做了依次衰减。5.添加缓存。没有假缓存的地方添加了缓存。小的优化最终没有达到性能的要求,但是也算是一些优化。

    结论

    缓存穿透在不发生的时候似乎觉得没有什么,一旦发生就会让人猝不及防。从每一个小细节着手,也许是开发高性能系统的重中之重。

纯属个人愚见,欢迎指正讨论。

猜你喜欢

转载自blog.csdn.net/tony_java_2017/article/details/80704232