一上来就优化SQL,结果白忙一场
有个朋友上周找我救急,说系统卡得不行,页面加载要十几秒。我问他查哪儿了,他头也不抬:‘肯定是数据库慢,我已经让DBA加索引去了。’
我打开监控一看,应用服务器CPU跑满,数据库连接池却空着一半。真正的问题是某个接口在循环里做加密计算,把线程全占死了。他折腾三天索引,根本没碰着病根。
把缓存当万能药,越用越慢
见过太多人一说性能差,第一反应就是加Redis。可缓存不是随便塞数据就行。有个电商项目,把整个商品详情页序列化后丢进Redis,单条数据快2MB。结果内存撑爆,频繁GC,反而比直接查数据库还慢。
更离谱的是缓存失效策略乱搞。设置10分钟过期,可高峰期每秒上万请求打进来,缓存一崩,雪崩效应直接压垮数据库。缓存要用,但得讲方法,不是扔进去就完事。
忽视网络传输的隐性开销
微服务拆得精细,接口调来调去,动不动就十几个HTTP请求串成一条链。每个看着只要50毫秒,合起来半秒没了。再加上序列化反序列化的成本,数据量一大,光在网络上传输就耗掉大半时间。
有次查问题,发现一个列表页要从三个服务拉数据,前端等得花儿都谢了。后来改成聚合接口,一次返回,响应直接降到200毫秒以内。别小看网络延迟,积少成多要命得很。
代码里的“看似无害”操作
下面这段代码看着挺正常:
for (int i = 0; i < userList.size(); i++) {
User user = userService.getById(userList.get(i).getId());
Order order = orderService.getByUserId(user.getId());
result.add(process(user, order));
}可你想想,循环一百次,就查一百次用户、一百次订单。数据库来回通信上百趟。换成批量查询,两三个SQL搞定的事,硬生生搞成N+1查询陷阱。
只盯着平均值,放过真凶
监控面板上写着“平均响应时间200ms”,大家就安心了。可实际上,90%的请求是100ms内完成的,剩下10%拖到了2秒以上。用户体验早就炸了。
有个API上线后投诉不断,查日志才发现是某些特殊参数触发了全表扫描。平均值被拉低了,但那部分用户已经点不动按钮了。看P95、P99才是正道。
别让日志拖后腿
调试时打满日志,上线忘了关。INFO级别记录每个请求参数,每天生成几十GB日志。磁盘IO跑满,服务开始卡顿。更狠的是有人在循环里打日志,一条请求输出上千行,写日志的时间比业务逻辑还长。
日志要有节制,敏感信息不该打,高频路径尽量简洁。必要时异步写入,别让记录过程影响主流程。