产生的原因大致可以分为两种:
1.常驻内存的PHP脚本长时间执行,未释放内存。
2.数据查询过大,导致内存撑爆。
第一种主要表现在一些 php 运行的 脚本,比如 作为消息队列的消费者,进行逻辑处理,一直监听消息,处理过程中累积的变量数据占用内存。这种解决的思路可以通过 释放变量或者缩短脚本的持续时间来处理,比如:
作为队列的消费者常驻内存,可以根据业务的调用量来定时重启,来达到释放内存的效果
作为定时脚本,可以规定每次执行的数据量范围,通过多次执行脚本替代一次执行脚本
处理过程中不要缓存数据(区分 fpm 和 cli 模式, fpm可以使用对象来缓存数据,达到每次请求內访问相同的数据不用再查询数据库,但是 cli 模式下最好不要使用)
研究所用的框架,是否会存储信息,比如 ci 框架的 db, 默认会把所有执行的sql语句都保存在 实例中,这样就会导致数据库交互越多,占用的内存就越大,可以把 db 对应的 save_queries 设置成 false,在消费者这种场景下不进行存储,会对内存提升的更好。
第二种主要表现在与一些数据库或者中间件进行数据传输时,数据量太大导致内存溢出,查询数据查出来几百万,读取大量的excel数据等等。这种解决的思路可以通过分片,分段的方式来处理,比如:
分多次从数据源获取数据
每次执行后进行变量的释放 unset(主要针对较大的变量)
适当的扩充内存 ini_set('memory_limit', '512M'),这种只适用于一些时间较短的脚本,在 fpm下不建议
总结: 常见的内存溢出主要是出现在cli模式下, fpm模式下一般不会出现,因为一次api请求结束后会自动释放内存, 而 cli 是常驻内存的,只有结束的时候才会释放。
网友评论