内存泄漏和内存溢出

内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。

内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

memory leak会最终会导致out of memory!

内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。

1.泄漏原因:
一.没有及时释放大变量

二.php-fpm造成的内存泄漏。

三.就是第三方扩展本身实现存在问题

解决办法:

临时办法:查看php-fpm内存占用情况  # ps -ylC php-fpm –sort:rss //按rss排序 直接kill -9 pid号(或cron定时脚本清理)

针对原因一:用完及时销毁变量

针对原因二:配置优化

1.php-fpm.conf中有个参数pm.max_requests,等同于PHP_FCGI_MAX_REQUESTS。意思是一个fpm进程处理多少个请求后自动杀掉另起新进程(默认关闭,开启,适当降低该值)。

2.max_children,这个是每次php-fpm会建立多少个进程,这样实际上的内存消耗是max_children乘以max_requests每个请求使用内存,根据这个我们可以预估一下内存的使用情况,就不用再写脚本去kill了
3.PHP配置文件里面的memory_limit 这个东西,其实,它限制的只是这个“请求处理”的内存。

wordpress上传图片显示HTTP错误

写文章想配一张图,上传发现http 错误,不应该啊,前一天还好好的。

排查:

1.图片大小并没有超过2m限制啊,难道是图片类型不对,那就改图片类型,上传,还是报同样错误。

2.换之前能成功的图片再次上传,可以成功啊,对比发现,两张图片大小差很多,怀疑是服务器对上传文件大小做了限制,那就改服务器配置试试

我用的nginx:在server内部加上  client_max_body_size 5m;

执行:

#nginx -t  //检查nginx配置是否正确

#nginx -s reload //重新加载nginx

再次上传图片,成功了!

crontab配置

有两种可以设置定时任务
1、在控制台执行crontab -e命令,输入定时规则,保存退出,这种设置针对用户级
2、直接编辑vim /etc/crontab,这种设置针对系统级

查看crontab状态:#systemctl status crond.service  或 #service crond status

启动:# service crond start

编辑:crontab -e

输入内容:* */1 * * * curl http://www.stonebaby.net >> /var/log/test.log 2>&1

一分钟执行一次,日志累加记录到test.log。其中1代表标准输出,2代表标准错误, 2>&1意思就是把命令执行的标准错误和标准输出都重定向到test.log里面去.

crontab -l//列出所有任务
crontab -l -u username//列出某一个用户任务
crontab -r//删除全部任务
crontab -r -u username//删除某一个用户任务

 

注意:

比如想每5分钟执行一次ntpdate 192.168.56.2

在crontab里写如下的内容是不行的

*/5 * * * * ntpdate 192.168.56.2
必须要写成这样

*/5 * * * * /usr/sbin/ntpdate 192.168.56.2

因为crontab里执行命令是没有PATH环境变量一说的,所以必须写绝对路径,否则crontab是找不到命令的

PHP多维数组按某个字段排序

$user_arr = array(
    array('age'=>32,'name'=>'a'),
    array('age'=>32,'name'=>'e'),
    array('age'=>34,'name'=>'re'),
    array('age'=>23,'name'=>'ere'),
    array('age'=>43,'name'=>'gf'),
    array('age'=>14,'name'=>'sds'),
);
$last_ages = array_column($user_arr,'name');
array_multisort($last_ages ,SORT_ASC,SORT_STRING ,$user_arr);
var_dump($user_arr);
//array_multisort第三个参数
可选。规定排序类型。可能的值:
  • SORT_REGULAR – 默认。把每一项按常规顺序排列(Standard ASCII,不改变类型)。
  • SORT_NUMERIC – 把每一项作为数字来处理。
  • SORT_STRING – 把每一项作为字符串来处理。
  • SORT_LOCALE_STRING – 把每一项作为字符串来处理,基于当前区域设置(可通过 setlocale() 进行更改)。
  • SORT_NATURAL – 把每一项作为字符串来处理,使用类似 natsort() 的自然排序。
  • SORT_FLAG_CASE – 可以结合(按位或)SORT_STRING 或 SORT_NATURAL 对字符串进行排序,不区分大小写。

Redis incr解决并发订单问题

场景:

1、新增订单,订单编码字段的规则为 “DD+yyyyMMdd+0000001。

2、每天订单量10万

思路:

1、假设redis服务器绝对安全

2、将订单编码存到缓存中(redis),其值只存“DD”+yyyyMMdd后面的数字部分;

对应的key为:key标识+yyyyMMdd,即每天一个key

3、每次生成订单编码时,先调用redis的incr方法,使其在原来编码的基础上加1,并返回结果

4、判断返回的结果,如果返回的是1,说明当前key之前不存在,为生成的新的一天的key,

6、如果redis宕机,或者key被删除,调用指定的接口,接口会去数据库查询今天最大的订单编码,

解析后,将其存在redis中,后面的订单编码再在此基础上自增

PHP实现:

$key = 'DD'.date('Ymd', time());
$id = $redis->incr($key);
$final_id = '';
        $l = strlen($id);
        if ($l>6) {
            $final_id =  $id;
        } else {
            $final_id = str_repeat(0, 6-$l).$id;//用0填充到6位数字
        }
echo $key.$final_id;

针对上面第6条
数据库查询当天最新订单号,处理提取出数值 $v,重新赋值给$key
$redis->set($key,$v);

分布式环境session共享解决方案

背景:

假设第一次访问服务A生成一个sessionid并且存入cookie中,第二次却访问服务B客户端会在cookie中读取sessionid加入到请求头中,如果在服务B通过sessionid没有找到对应的数据那么它创建一个新的并且将sessionid返回给客户端,这样并不能共享我们的Session无法达到我们想要的目的。

解决方案:

  • 使用cookie(安全性问题)
  • 使用Nginx中的ip绑定策略,同一个ip只能在指定的同一个机器访问(不支持负载均衡)
  • 利用数据库同步session(效率问题)
  • 使用token代替session
  • 存放在redis中

nginx解决方案

提供了ip_hash策略,可以保持用户ip进行hash值计算固定分配到某台服务器上,然后只要是该ip则会保持分配到该服务器上,保证用户访问的是同一台服务器,那么session问题就不存在了。这也是解决session共享的一种方式,也称为黏性session。但是假设一台tomcat服务器挂了的话,那么session也会丢失。所以比较好的方案是抽取session

Redis解决方案

1.  session数据如何在Redis中存储?

2.  session属性变更何时触发存储?

考虑到session中数据类似map的结构,采用redis中hash存储session数据比较合适,如果使用单个value存储session数据,不加锁的情况下,就会存在session覆盖的问题,因此使用hash存储session,每次只保存本次变更session属性的数据,避免了锁处理,性能更好

如果每改一个session的属性就触发存储,在变更较多session属性时会触发多次redis写操作,对性能也会有影响,我们是在每次请求处理完后,做一次session的写入,并且之写入变更过的属性

如果本次没有做session的更改, 是不会做redis写入的,仅当没有变更的session超过一个时间阀值(不变更session刷新过期时间的阀值),就会触发session保存,以便session能够延长有效期