加入收藏 | 设为首页 | 会员中心 | 我要投稿 鄂州站长网 (https://www.0711zz.com/)- 数据分析、网络、云渲染、应用安全、大数据!
当前位置: 首页 > 编程开发 > PHP > 正文

PHP应用:详解PHP使用Redis存储session时的一个Warning定位

发布时间:2020-07-09 06:52:29 所属栏目:PHP 来源:互联网
导读:介绍《PHP应用:详解PHP使用Redis存储session时的一个Warning定位》开发教程,希望对您有用。

《PHP应用:详解PHP使用Redis存储session时的一个Warning定位》要点:
本文介绍了PHP应用:详解PHP使用Redis存储session时的一个Warning定位,希望对您有用。如果有疑问,可以联系我们。

PHP实例1. 问题现象

PHP实例系统页面刷新的时候,偶尔会报错下面的Warnning,但是不经常出现:

PHP实例Warning: Unknown: Failed to write session data (Redis). Please verify that the current setting of session.save_path is correct (tcp://x.x.x.x:6379?auth=yyy) in Unknown on line 0

PHP实例看网络有人说是redis版本的问题、但是没有具体结论,那么本着学习的态度,自己试试看看能不能捉出这个bug.

PHP实例定位问题:

PHP实例查看PHP文件是否有设置session的地方,发现没有

PHP实例继续检查php配置文件,发现配置了session存储到redis里面

PHP实例
[Session]
session.save_handler = redis
session.save_path = "tcp://x.x.x.x:6379?auth=yyyy"
session.use_cookies = 1

PHP实例1、继续查看php Session扩展源代码,定位出错提示语在函数php_session_save_current_state中

PHP实例检查session扩展文件中出错提示:

PHP实例
static void php_session_save_current_state(TSRMLS_D) /* {{{ */
{
  int ret = FAILURE;
  //是否session数组
  IF_SESSION_VARS() {
    if (PS(mod_data) || PS(mod_user_implemented)) {
      char *val;
      int vallen;
     //变量编码
      val = php_session_encode(&vallen TSRMLS_CC);
      if (val) {
        //保存session数据
        ret = PS(mod)->s_write(&PS(mod_data),PS(id),val,vallen TSRMLS_CC);
        efree(val);
      } else {
        //清空session
        ret = PS(mod)->s_write(&PS(mod_data),"",0 TSRMLS_CC);
      }
    }
    //看出错提示语在这里
    if (ret == FAILURE) {
      php_error_docref(NULL TSRMLS_CC,E_WARNING,"Failed to write session data (%s). Please "
          "verify that the current setting of session.save_path "
          "is correct (%s)",PS(mod)->s_name,PS(save_path));
    }
  }
  if (PS(mod_data) || PS(mod_user_implemented)) {
    PS(mod)->s_close(&PS(mod_data) TSRMLS_CC);
  }
}
static void php_session_flush(TSRMLS_D){
  如果 (PS(session_status) == php_session_active)
    session_status = none
    这里调用...
    php_session_save_current_state
}

PHP实例下面两个函数调用:php_session_flush()

PHP实例
static PHP_FUNCTION(session_write_close)
{
  php_session_flush(TSRMLS_C);
}
static PHP_FUNCTION(session_register_shutdown){
}

PHP实例由上面可以看到,php_session_save_current_state是在 php_session_flush中调用,即在session保存、清空等刷新写session的时候会产生.

PHP实例由php seesion源码没有发现什么问题,突然想到会不会是Redis本身有没有啥问题,导致的写出错.因而继续从redis里面找问题:

PHP实例Redis问题定位

PHP实例1. 首先查看Redis日志文件:

PHP实例看到如下每5分钟会刷新一下如下log:

PHP实例
[16723] 04 Jul 15:15:01.987 # Server started,Redis version 2.8.9
[16723] 04 Jul 15:15:01.987 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
[16723] 04 Jul 15:15:01.996 * DB loaded from disk: 0.008 seconds
[16723] 04 Jul 15:15:01.996 * The server is now ready to accept connections on port 6379

PHP实例怀疑这就是问题的PHP写日志失败的原因了.那么Redis为啥会5分钟重启呢?继续追查!

PHP实例2. 是系统内存不够、Redis core了?

PHP实例查看系统和Redis内存使用状态:

PHP实例系统内存状态:

PHP实例
$ free -m
       total    used    free   shared  buffers   cached
Mem:     3516    3171    345     0    684    1680
-/+ buffers/cache:    806    2709
Swap:     2055    724    1330

PHP实例Redis服务器占用的内存状态:

PHP实例
used_memory:2841648
used_memory_human:2.71M
used_memory_rss:3710976
used_memory_peak:2877576
used_memory_peak_human:2.74M
used_memory_lua:33792
mem_fragmentation_ratio:1.31
mem_allocator:jemalloc-3.2.0

PHP实例可以看到Redis其实内存占用非常少.redis重启原因暂且不明.

PHP实例3. 定时脚本

PHP实例因为重启日志5分钟一次、非常规律,因而怀疑是不是别的原因导致Redis重启,比如定时脚本.

PHP实例因为本人没有root corntab权限,找老板提权,看到赫然存在着一个crontab,5分钟监控一次redis.

PHP实例如下:

PHP实例
/5 * * * /data/scripts/check_redis.sh >/dev/null 2>&1 ##check_redis.tag.1

PHP实例查看脚本内容

PHP实例
PORT='6379'
ETH1_ADDR=`/sbin/ifconfig eth1 | awk -F ':' '/inet addr/{print $2}' | sed 's/[a-zA-Z ]//g'`
retval=`nmap --system-dns -sT -p ${PORT} ${ETH1_ADDR} | grep open`
if [ "${retval}X" = "X" ]; then
    /sbin/service redis restart >/dev/null 2>&1
fi

PHP实例这是一个检查Redis端口是否提供服务的脚本,如果检查不成功,就拉起Redis.

PHP实例可以看到这个脚本本来没有什么问题.

PHP实例但是:通过手动执行这个命令发现:

PHP实例这台机器没有安装nmap 这个命令,

PHP实例所以这个脚本最后总是执行失败!然后Redis重启.

PHP实例因为问题根源找到了,找运维安装相关命令,问题解决.

PHP实例以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家PHP.

(编辑:鄂州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读