浅析PHP中Session可能会引起并发问题


Posted in PHP onJuly 23, 2015

在进行Web应用程序开发的时候,人们经常会用Session存储数据。但可能有人不知道,在PHP中,Session使用不当可能会引起并发问题。印度医疗行业软件解决方案提供商Plus91 Technologies高级工程师Kishan Gor在个人博客上对这个问题进行了阐释。

如果同一个客户端并发发送多个请求,而每个请求都使用了Session,那么PHP Session锁的存在会导致服务器串行响应这些请求,而不是并行。这是因为在默认情况下,PHP使用文件存储Session数据。对于每一个新的Session,PHP会创建一个文件,并持续向其中写入数据。所以,每次调用session_start()方法,就会打开Session文件,并取得文件的独占锁。这样,如果服务器脚本正在处理一个请求,而客户端又发送了一个同样需要使用Session的请求,那么后一个请求会阻塞,直至前一个请求处理完成释放了文件上的独占锁。不过,这只限于来自同一个客户端的多个请求,也就是说,来自一个客户端的请求并不会阻塞另一个客户端的请求。

如果脚本很短,这通常没有问题。但如果脚本运行时间比较长,那就可能会产生问题。在现代Web应用程序开发中,有一个非常常见的情况,就是使用AJAX技术在同一个页面内发送多个请求获取数据。如果这些请求都需要使用Session,那么第一个请求到达服务器后会取得Session锁,其它请求就必须等待,所有请求将串行处理,即使它们彼此之间并没有依赖关系。这将大大增加页面的响应时间。

有一个方法可以避免这个问题,就是在使用完Session以后立即调用session_write_close()方法关闭Session。这样Session锁就会释放,即使当前脚本还在等在处理。需要注意的是,调用该方法后,当前脚本就不能进一步操作Session了。

需要特别指出的是,本文所陈述的问题和观点只适用于使用session_start()方法的PHP默认Session管理模式。比如,有用户就指出,如果将应用程序托管在AWS EC2上,并正确配置DynamoDB,Session锁定问题就不会出现。

附上一份实例代码:

Session.php

<?php

final class SessionController extends YafController_Abstract
{
  public function setUserFileAction()
  {
    session_start();
    $_SESSION['user_name'] = 'xudianyang';
    $_SESSION['user_id']  = '123';

    sleep(3);
    echo json_encode($_SESSION);
    return false;
  }

  public function setLoginFileAction()
  {
    session_start();
    $_SESSION['last_time'] = time();

    echo json_encode($_SESSION);
    return false;
  }

  public function indexFileAction()
  {
    // Auto Rend View
  }

  public function getSessionFileAction()
  {
    session_start();
    var_dump($_SESSION);

    return false;
  }

  public function setUserRedisAction()
  {
    $session = CoreFactory::session();
    $session->set('user_name', 'xudianyang');
    $session->set('user_id', '123');

    sleep(3);
    echo json_encode($_SESSION);
    return false;
  }

  public function setLoginRedisAction()
  {
    $session = CoreFactory::session();
    $session->set('last_time', time());

    echo json_encode($_SESSION);
    return false;
  }

  public function indexRedisAction()
  {
    // Auto Rend View
  }

  public function getSessionRedisAction()
  {
    $session = CoreFactory::session();
    var_dump($_SESSION);

    return false;
  }
}

indexfile.phtml

<!DOCTYPE html>
<html>
<head>
 <title>测试session并发锁问题</title>
 <meta charset="utf-8">
 <script type="text/javascript" src="/assets/js/jquery-1.10.2.min.js"></script>
 <script type="text/javascript">
   $.ajax({
     url: "/session/setUserFile",
     type: "get",
     dataType: "json",
     success: function(response){
       console.info(response.last_time);
     }
   });
   setTimeout(function(){
     $.ajax({
       url: "/session/setLoginFile",
       type: "get",
       dataType: "json",
       success: function(response){
         console.info(response.last_time);
       }
     });
   }, 300);
 </script>
</head>
<body>
同时发起2两个ajax请求
</body>
</html>

indexredis.phtml

<!DOCTYPE html>
<html>
<head>
 <title>测试session并发锁问题</title>
 <meta charset="utf-8">
 <script type="text/javascript" src="/assets/js/jquery-1.10.2.min.js"></script>
 <script type="text/javascript">
   $.ajax({
     url: "/session/setUserRedis",
     type: "get",
     dataType: "json",
     success: function(response){
       console.info(response.last_time);
     }
   });
   setTimeout(function(){
     $.ajax({
       url: "/session/setLoginRedis",
       type: "get",
       dataType: "json",
       success: function(response){
         console.info(response.last_time);
       }
     });
   }, 300);
 </script>
</head>
<body>
同时发起2两个ajax请求
</body>
</html>

以上所述就是本文的全部内容了,希望大家能够喜欢。

PHP 相关文章推荐
PHP 中的面向对象编程:通向大型 PHP 工程的办法
Dec 03 PHP
php与paypal整合方法
Nov 28 PHP
php提交表单时判断 if($_POST[submit])与 if(isset($_POST[submit])) 的区别
Feb 08 PHP
PHP多线程类及用法实例
Dec 03 PHP
php在数组中查找指定值的方法
Mar 17 PHP
5款适合PHP使用的HTML编辑器推荐
Jul 03 PHP
PHP生成唯一订单号
Jul 05 PHP
php邮箱地址正则表达式验证
Nov 13 PHP
PHP接收json 并将接收数据插入数据库的实现代码
Dec 01 PHP
php实现将base64格式图片保存在指定目录的方法
Oct 13 PHP
基于swoole实现多人聊天室
Jun 14 PHP
ThinkPHP中获取指定日期后工作日的具体日期方法
Oct 14 PHP
PHP技术开发微信公众平台
Jul 22 #PHP
PHP使用array_merge重新排列数组下标的方法
Jul 22 #PHP
PHP结合jQuery实现找回密码
Jul 22 #PHP
使用PHP生成二维码的方法汇总
Jul 22 #PHP
使用PHP编写发红包程序
Jul 22 #PHP
解决nginx不支持thinkphp中pathinfo的问题
Jul 21 #PHP
php 把数字转换成汉字的代码
Jul 21 #PHP
You might like
十天学会php之第三天
2006/10/09 PHP
PHP中把stdClass Object转array的几个方法
2014/05/08 PHP
thinkPHP5分页功能实现方法分析
2017/10/25 PHP
Laravel中unique和exists验证规则的优化详解
2018/01/28 PHP
php输出控制函数和输出函数生成静态页面
2019/06/27 PHP
Moment.js 不容错过的超棒Javascript日期处理类库
2012/04/15 Javascript
等待指定时间后自动跳转或关闭当前页面的js代码
2013/07/09 Javascript
JS中window.open全屏命令解析及使用示例
2013/12/11 Javascript
禁用Tab键JS代码兼容Firefox和IE
2014/04/18 Javascript
iframe实用操作锦集
2014/04/22 Javascript
基于jquery实现的可编辑下拉框实现代码
2014/08/02 Javascript
JavaScript获取表格(table)当前行的值、删除行、增加行
2015/07/03 Javascript
Node.js的文件权限及读写flag详解
2016/10/11 Javascript
js仿搜狐视频记录片列表展示效果
2020/05/30 Javascript
JavaScript全屏和退出全屏事件总结(附代码)
2017/08/17 Javascript
ExtJs使用自定义插件动态保存表头配置(隐藏或显示)
2018/09/25 Javascript
JS温故而知新之变量提升和时间死区
2019/01/27 Javascript
Node.js事件的正确使用方法
2019/04/05 Javascript
JavaScript如何处理移动端拍摄图片旋转问题
2019/11/16 Javascript
[02:38]DOTA2英雄基础教程 噬魂鬼
2014/01/03 DOTA
Python程序员开发中常犯的10个错误
2014/07/07 Python
Python实现对文件进行单词划分并去重排序操作示例
2018/07/10 Python
python判断字符串或者集合是否为空的实例
2019/01/23 Python
Python实现CNN的多通道输入实例
2020/01/17 Python
python json 递归打印所有json子节点信息的例子
2020/02/27 Python
使用javascript和HTML5 Canvas画的四渐变色播放按钮效果
2014/04/10 HTML / CSS
Agoda香港:全球特价酒店预订
2017/05/07 全球购物
建筑工程技术应届生求职信
2013/11/17 职场文书
信息技术毕业生自荐信范文
2014/03/13 职场文书
个人工作表现评语
2014/04/30 职场文书
党的群众路线教育实践活动对照检查材料范文
2014/09/24 职场文书
专题民主生活会对照检查材料思想汇报
2014/09/29 职场文书
应届生求职自荐信范文
2015/03/04 职场文书
详解Java线程池是如何重复利用空闲线程的
2021/06/26 Java/Android
MySQL的prepare使用以及遇到的bug
2022/05/11 MySQL
windows server2012 R2下安装PaddleOCR服务的的详细步骤
2022/09/23 Servers