转载

PHP函数sem_get引起的“No space lelf on device”问题解决记录

1.  问题表现:

接收到告警,部分接口异常。

2.  问题追查:

首先,机器日志中忽然出现很多的 flow_lock Faild to create semaphore 的错误。

追查系统中的代码实现后,发现是 sem_get 函数引起,该函数用于根据一个 key 值来获取一个系统 System V 信号量的引用。

代码位置:

PHP函数sem_get引起的“No space lelf on device”问题解决记录

我单独在指定机器上执行上述语句,发现了 Warning 信息: No space lelf on device ,原本以为是磁盘或者内存的空间不足,实际检查后才发现是信号量被耗尽了。

PHP函数sem_get引起的“No space lelf on device”问题解决记录

信号量是一种有限资源,通过 Linux 命令,查看系统信号量的限制数目是 1024 个。

PHP函数sem_get引起的“No space lelf on device”问题解决记录

Web 机器实际已经使用掉的信号量数目已经达到 1024 个,也就是说,可用的信号量已经被用完了。原因,已经比较明显了,就是 信号量被申请使用之后,没有被释放

PHP函数sem_get引起的“No space lelf on device”问题解决记录

于是我们追查代码源头,发现确实如此,这里的 sem_release 是类似解锁的意思,并非释放这个信号量,真正释放的函数是 sem_remove

PHP函数sem_get引起的“No space lelf on device”问题解决记录

sem_release 的官方文档说明:

PHP函数sem_get引起的“No space lelf on device”问题解决记录

至此,找到问题所在。这个问题潜伏了很久,系统经常很长时间,累计申请了信号量而没有释放,慢慢达到 1024 个,最终触发该问题。

3.  问题解决方式:

1 )使用 root 权限手动释放信号量,如果有多台机器,每一台都要执行。

for semid in `ipcs -s | cut -f2 -d""`; do ipcrm -s $semid; done

2 )重启 Apache 服务,之后,信号量的使用情况,恢复到正常的数目。

PHP函数sem_get引起的“No space lelf on device”问题解决记录

关键代码位置:

PHP函数sem_get引起的“No space lelf on device”问题解决记录

函数 ams_sem_remove 会执行 sem_remove 的释放操作。

4.  问题小结:

Sem_get 系列函数,通过信号量来达到类似 Linux 的互斥量( mutex )锁的效果,对一个内存共享对象加锁和解锁的方式,来控制并发请求数量(类似线程安全)。出问题的原因,是长期运行下,申请占用了很多个信号量,并且缺少 sem_remove 的释放操作。

PHP函数sem_get引起的“No space lelf on device”问题解决记录

正文到此结束
Loading...