PHP-在数据库中存储会话

PHP-在数据库中存储会话,php,mysql,apache,amazon-ec2,load-balancing,Php,Mysql,Apache,Amazon Ec2,Load Balancing,我正在设置一个带有负载平衡器的EC2集群。我有一个单独的数据库服务器,上面运行着mysql。我有3台Web服务器在运行,主要是为了实现高可用性,当然,它的循环负载平衡似乎是这样的,所以您访问的每个页面都会得到一台不同的服务器,这会使您的会话中断 我正在尝试设置PHP以将其存储在DB中。我已经设置了一个表,并设置了所有功能(打开、关闭等)。我已经确定: session_set_save_handler('_open', '_close',

我正在设置一个带有负载平衡器的EC2集群。我有一个单独的数据库服务器,上面运行着mysql。我有3台Web服务器在运行,主要是为了实现高可用性,当然,它的循环负载平衡似乎是这样的,所以您访问的每个页面都会得到一台不同的服务器,这会使您的会话中断

我正在尝试设置PHP以将其存储在DB中。我已经设置了一个表,并设置了所有功能(打开、关闭等)。我已经确定:

session_set_save_handler('_open',
                         '_close',
                         '_read',
                         '_write',
                         '_destroy',
                         '_clean');
但是,当我登录或在网站上做任何事情时,我检查了表格,但什么都没有写。我不确定是否需要更改php.ini文件中的某些内容。如果是,更改的值是什么

谢谢

编辑:功能:

function _open(){    
    global $con;
    connect();
} 
    
function _close(){  
    global $con;  
    //mysql_close();
}

function _read($id){    
    global $con;    
    $id = mysql_real_escape_string($id);     
    $sql = "SELECT data FROM sessions WHERE id = '$id'";     
    if ($result = mysql_query($sql, $con)) {        
        if (mysql_num_rows($result)) {            
            $record = mysql_fetch_assoc($result);             
            return $record['data'];        
        }    
    }     
    return '';
}

function _write($id, $data)
{
    global $con;
 
    $access = time();
 
    $id = mysql_real_escape_string($id);
    $access = mysql_real_escape_string($access);
    $data = mysql_real_escape_string($data);
 
    $sql = "REPLACE
            INTO    sessions
            VALUES  ('$id', '$access', '$data')";
 
    return mysql_query($sql, $con);
}

function _destroy($id)
{
   global $con;
    $id = mysql_real_escape_string($id);
    $sql = "DELETE
            FROM   sessions
            WHERE  id = '$id'";
    return mysql_query($sql, $con);
}

function _clean($max)
{
    global $con;
 
    $old = time() - $max;
    $old = mysql_real_escape_string($old);
 
    $sql = "DELETE
            FROM   sessions
            WHERE  access < '$old'";
 
    return mysql_query($sql, $con);
}

session_set_save_handler('_open',
                         '_close',
                         '_read',
                         '_write',
                         '_destroy',
                         '_clean');
函数_open(){
全球$con;
connect();
} 
函数_close(){
全球$con;
//mysql_close();
}
函数_read($id){
全球$con;
$id=mysql\u real\u escape\u字符串($id);
$sql=“从id=“$id”的会话中选择数据”;
如果($result=mysql\u查询($sql,$con)){
如果(mysql_num_rows($result)){
$record=mysql\u fetch\u assoc($result);
返回$record['data'];
}    
}     
返回“”;
}
函数_write($id,$data)
{
全球$con;
$access=time();
$id=mysql\u real\u escape\u字符串($id);
$access=mysql\u real\u escape\u string($access);
$data=mysql\u real\u escape\u字符串($data);
$sql=“替换
进入会议
值(“$id”、“$access”、“$data”)”;
返回mysql\u查询($sql,$con);
}
函数_销毁($id)
{
全球$con;
$id=mysql\u real\u escape\u字符串($id);
$sql=“删除
来自会话
其中id=“$id”;
返回mysql\u查询($sql,$con);
}
功能清洁($max)
{
全球$con;
$old=time()-$max;
$old=mysql\u real\u escape\u字符串($old);
$sql=“删除
来自会话
其中访问<'$old';
返回mysql\u查询($sql,$con);
}
会话设置保存处理程序(“打开”),
"关闭",,
"读",,
"写",,
"销毁",,
"清洁",;

您正在使用的功能将中断正常会话功能并插入代码以执行操作,然后继续执行其他内部功能

在函数中,如果您没有真正执行任何与会话相关的操作(例如“\u open”和“\u close”),则需要返回一些内容来执行命令,否则它将立即消失

例如:

function _open($save_path, $session_name){    
    global $con;
    connect();

    return true; //Do nothing but carry on
} 

function _close(){  
    global $con;  
    //mysql_close();

    return true; //Do nothing but carry on
}

实际上,这并不是你问题的答案,但是如果你真的需要高可用性,我可以建议在mysql中存储会话不是一个好方法

更好的做法是:将会话放在memcache中。Memcache服务器,易于安装。Memcache客户端易于安装,php支持在Memcache中存储会话,无需编程!!!Memcache将数据存储在内存中,而不是磁盘中,速度更快

在这里你可以看到一篇关于这方面的好文章:


祝你好运

为什么你不能用饼干?让脚本检查cookies是否存在,然后从那里读取值。除非安全是个问题。。我建议在会话上使用cookie,以实现廉价的可伸缩性。在数据库中写入会话将不太好,可能会导致无缘无故地运行昂贵的查询

会话的最佳数据库是Redis或MonogDB,而不是MySQL和memcached。您可以根据获得的流量使用memcached,但Redis或MongoDB是一个更具可伸缩性的数据库。另外,由于您使用的是EC2,您可能需要查看AmazonSimpleDB。它是一个键/值存储,因此它应该适合会话

我个人会使用MongoDB,因为您不仅可以将会话存储在那里,还可以将MySQL中的内容缓存在那里,并将其他数据存储在Mongo中……或者考虑将站点的数据库全部转换,因为您可能会爱上MongoDB=)


您还可以在应用程序Cookies下查看HAProxy的设置。这可能也会对您有所帮助。

您可以发布有问题的函数吗?它们在一个类中吗,它们是独立的函数吗,等等…刚刚编辑了这篇文章,谢谢:)我认为您不需要为“\u write”和“\u clean”返回查询结果对象。尝试用return true替换它们。(并保持“_destroy”的原样)“_open”还接受两个变量:$save_path和$session_name。加上我上面提到的那些,还是什么都没有。我很沮丧。。。有没有类似的调试,我可以看到到底是怎么回事?它都是基于标题的,所以你不能随意丢弃你的东西。您可以尝试var_export或其他函数,并将所有输出路由到一个全局字符串变量,然后在结尾回显?不太确定,你已经把我的大部分想法都浪费在这个问题上了。在一个高流量的网站上,要么因为达到memcached配置的限制而开始左右丢失会话,要么随着concurrents会话数量的增加,您必须购买越来越多的RAM。RAM不便宜。另一方面,硬盘是……这是我们正在谈论的EC2。如果OP担心其主实例中的内存,那么这些小预算实例的功能足以承载一个专用的memcached实例。在这个特定的场景中,内存不是真正的问题。Memcache不是会话数据库的替代品。添加一个性能层很好,但是您仍然应该写入一个更持久的存储,然后在缓存未命中时读取存储。