“原来100个人干50个人的活,现在裁到50个人,还是干25个人的活。”
老板觉得奇怪:人少了一半,为什么效率没有翻倍?
很多团队裁员后都会遇到类似现象。表面看是“人效下降”,实际上是系统里的瓶颈根本没变。
技术团队尤其明显。
以前100个开发,每天提交大量代码,但线上问题多、发布慢、接口越来越卡。裁掉一半人以后,代码提交少了,会议少了,但系统依旧慢,故障依旧发生。
因为真正限制团队产出的,通常不是人数,而是等待。
数据库在等锁,线程池在等队列,接口在等下游,发布在等审批。
人只是把这些等待放大了。
一个接口变慢,先别急着加机器
线上有个订单查询接口:
QPS: 800
P99: 3.2s
平均RT: 450ms
CPU: 35%
很多人的第一反应:
“CPU这么低,是不是机器少了?”
加机器。
结果:
扩容前:
4台应用服务器
扩容后:
8台应用服务器
P99:
3.2s -> 3.1s
几乎没变化。
因为CPU根本不是瓶颈。
看调用链:
order-api
|
|-- redis 5ms
|
|-- mysql 2800ms
|
|-- lock wait 2500ms
问题已经出来了。
SQL执行时间不是慢,而是在等锁。
例如:
update account
set balance = balance - 100
where user_id = 10086;
高峰期间大量请求更新同一个用户账户。
线程全部堵在:
等待数据库锁
等待
等待
等待
你增加服务器,只是增加更多线程进入等待区。
线程池满了,不一定是线程少
很多线上事故来自这种配置:
@Bean
public ExecutorService executor(){
return new ThreadPoolExecutor(
50,
50,
60,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>()
);
}
看起来:
“50个线程够用了。”
问题是队列无限。
线上突然流量上涨:
active thread:
0s 50
10s 50
30s 50
queue:
0
500
3000
10000
接口没有立即失败。
而是慢慢排队。
用户看到:
请求超时
请求超时
请求超时
真正耗时:
业务执行:
80ms
排队等待:
3000ms
但是开发看到业务代码:
“才80ms啊。”
因为查错地方了。
正确看线程池:
ThreadPoolExecutor pool =
(ThreadPoolExecutor) executor;
System.out.println(
"active=" + pool.getActiveCount()
);
System.out.println(
"queue=" + pool.getQueue().size()
);
重点不是:
“线程执行多久。”
而是:
“请求等线程多久。”
数据库优化,先拆等待位置
很多优化方案一上来就是:
加索引
分库分表
换数据库
但线上排查顺序不是这样。
一个SQL耗时:
3000ms
先拆:
获取连接:
20ms
SQL执行:
50ms
锁等待:
2900ms
返回:
30ms
如果是连接池问题:
HikariPool-1 - Connection is not available
看:
spring:
datasource:
hikari:
maximum-pool-size: 30
connection-timeout: 3000
如果是连接不够:
active=30
idle=0
pending=200
加连接池可能有效。
但如果:
active=10
idle=20
SQL慢
加连接池没有意义。
只是让更多SQL同时攻击数据库。
Redis慢,也可能不是Redis慢
常见报警:
redis command latency > 100ms
很多人直接升级Redis配置。
但是实际情况可能:
业务线程
|
| 获取分布式锁
|
| 等待锁释放
|
Redis GET执行正常
例如:
String lockKey = "pay:" + orderId;
boolean success =
redis.setIfAbsent(
lockKey,
"1",
30,
TimeUnit.SECONDS
);
如果业务异常:
线程A
获取锁
执行支付
异常退出
锁30秒后释放
线程B
等待30秒
Redis没慢。
业务设计慢。
应该:
try{
doPay();
}finally{
redis.delete(lockKey);
}
同时设置合理超时时间。
为什么裁员后效率没提升?
因为很多团队的问题不是:
100个人
50个人
而是:
100个人
|
等待数据库
|
等待审批
|
等待发布
|
等待线上恢复
人数减少,只减少了制造等待的人。
没有减少等待本身。
真正提升效率,要找到系统里的那个排队点。
代码慢,看线程等待。
数据库慢,看锁等待。
接口慢,看调用链等待。
团队慢,看流程等待。
裁员改变的是资源数量,优化改变的是系统结构。