非常典型,但是又非常容易出错的地方
场景:团队内造了一个轮子,即使用Redis实现分布式锁。
//加锁
public boolean tryAcquire(String key,long expireTime);
//释放锁
public boolean release(String key);
业务代码:
public void consume(){
if(tryAcquire(key,30)){
try{
//业务逻辑,调用接口全量的拉取数据
}finally{
release(key);
}
}
}
然后上线后,CPU飙升。
详细的排查过程可以参考下文:
JVM那点事-JDK命令行工具+JProfiler的使用(排查线上问题)
JVM那点事—show-busy-java-threads排查CPU性能问题
问题定位到就是
- GC线程数量上升,导致CPU利用率飙升。
- 日志出现的是tryAcquire操作无效,大量线程并发的调用接口拉取全量数据;
最终定位的原因就是:tryAcquire中的expireTime单位是ms,而开发的同学以为这个单位是秒,以为设置30s的超时时间,造成了一次生产事故。
得到的教训是:方法的参数命名要规范,不能给人一种很模糊的感觉;
网友评论