主要针对接口响应慢
- 问题定位
- 解决方案
1. 定位
接口响应时间太长,怎么去定位问题?
- 网络问题(ping一下就知道了,一般不会有)
- 根据自己多年写bug的经验, 扒拉一下代码看一下看问题出在哪里了?
① 循环查询 ②计算量大 ③慢sql - 利用工具监控, 远程debug 或者 Arthas(阿尔萨斯)
Arthas的使用后续会专门写一篇,先看这个arthas:Java调试利器,线上Debug不是梦
2. 解决方案
- 避免循环查询
避免在循环中, 查询(插入,调用接口),避免多次 IO, 可以改为批处理 - 空间换时间
使用map,redis等技术,一次性把数据加载进内存中,然后处理 - 异步处理
对于不用立即返回的数据, 可以放在后台慢慢处理的, 可以使用异步线程,后端慢慢处理, 如文件上传内容解析 - 预处理
提前结算出结果,放在缓存或者数据库中,需要结果的直接取,
常用场景, 以年,月,日为维度统计的结果,用定时器定时触发计算出结果 - 多线程并行计算
串行计算逻辑简单, 当计算量大的时候, 可以考虑并行计算,
避免锁竞争的方法是,把数据进行分类, 各组数据互不相干,直接塞进线程计算
即使最终结果是串行计算的结果, 也可以将计算过程并行化,然后将结果合并 - 慢sql
慢sql 牵扯到sql优化 可以参考MySQL性能管理及架构设计
使用执行计划 explain 可以分析慢sql部分原因
sql常用优化策略: ①使用索引(索引建多了 也会影响效率)
②避免表关联(必须使用的情况下,可以用小表关联大表) ③减少子查询
④避免全表扫描, 常用策略如下
(1)避免在 where 子句中对字段进行 null 值判断(2)避免在 where 子句中使用!=或<>操作符(3)避免在 where 子句中使用 or 来连接条件(4)in 和 not in ,like 也要慎用,可用exists 代替in(子查询中的表小,就用in,否则就用exists; not in 对内外表都是全表扫描,not exists 子查询依然能用到索引 ; 对于连续的数值,能用 between 就不要用 in )(5)避免在where子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描(6)like左模糊匹配 like '***%'
- 归档 数据量特别大,且数据利用率不高,可以将不常用的数据进行归档
- 热数据特别多的情况下, 更换数据库,如ES,Hbase之类的更适合大数据的数据库
- 事务
尤其是大事务, 由于事务没有提交,会导致数据库连接一直被占用,有可能引发死锁等问题