您的位置:首页 > 数据库 > Memcache

PHP实现多服务器session共享之memcache共享

2011-09-23 15:43 633 查看
再自定义一套session处理机制,关于session的实现方法我就不再多讲,直接贴程序了。

<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
//===========================================
// 程序:   Memcache-Based Session Class
// 功能:   基于Memcache存储的 Session 功能类
// 作者:    yejr
// 网站:    http://imysql.cn // 时间:    2007-01-05
//===========================================

/**
* 文件:    MemcacheSession.inc.php
* 类名:    MemcacheSession Class
* 功能:    自主实现基于Memcache存储的 Session 功能
* 描述:    这个类就是实现Session的功能,基本上是通过
*          设置客户端的Cookie来保存SessionID,
*          然后把用户的数据保存在服务器端,最后通过
*          Cookie中的Session Id来确定一个数据是否是用户的,
*          然后进行相应的数据操作
*
*          本方式适合Memcache内存方式存储Session数据的方式,
*          同时如果构建分布式的Memcache服务器,
*          能够保存相当多缓存数据,并且适合用户量比较多并发比较大的情况
*
* 注意: 本类必须要求PHP安装了Memcache扩展或者必须有Memcache的PHP API
*       获取Memcache扩展请访问: http://pecl.php.net */

//设定 SESSION 有效时间,单位是 秒
define('SESS_LIFTTIME', 3600);

//定义memcache配置信息
define('MEMCACHE_HOST', 'localhost');
define('MEMCACHE_PORT', '10000');

if (!defined('MemcacheSession'))
{
define('MemcacheSession',    TRUE);

class MemacheSession
{

// {{{ 类成员属性定义
static  $mSessSavePath;
static  $mSessName;
static  $mMemcacheObj;
// }}}

// {{{ 初始化构造函数
/**
* 构造函数
*
* @param string $login_user    登录用户
* @param int $login_type       用户类型
* @param string $login_sess    登录Session值
* @return Esession
*/
public function __construct()
{
//我的memcache是以php模块的方式编译进去的,可以直接调用
//如果没有,就请自己包含 Memcache-client.php 文件
if (!class_exists('Memcache') || !function_exists('memcache_connect'))
{
die('Fatal Error:Can not load Memcache extension!');
}

if (!empty(self::$mMemcacheObj) && is_object(self::$mMemcacheObj))
{
return false;
}

self::$mMemcacheObj = new Memcache;

if (!self::$mMemcacheObj->connect(MEMCACHE_HOST , MEMCACHE_PORT))
{
die('Fatal Error: Can not connect to memcache host '. MEMCACHE_HOST .':'. MEMCACHE_PORT);
}

return TRUE;
}
// }}}

/** {{{ sessOpen($pSavePath, $name)
*
* @param   String  $pSavePath
* @param   String  $pSessName
*
* @return  Bool    TRUE/FALSE
*/
public function sessOpen($pSavePath = '', $pSessName = '')
{
self::$mSessSavePath    = $pSavePath;
self::$mSessName        = $pSessName;

return TRUE;
}
// }}}

/** {{{ sessClose()
*
* @param   NULL
*
* @return  Bool    TRUE/FALSE
*/
public function sessClose()
{
return TRUE;
}
// }}}

/** {{{ sessRead($wSessId)
*
* @param   String  $wSessId
*
* @return  Bool    TRUE/FALSE
*/
public function sessRead($wSessId = '')
{
$wData = self::$mMemcacheObj->get($wSessId);

//先读数据,如果没有,就初始化一个
if (!empty($wData))
{
return $wData;
}
else
{
//初始化一条空记录
$ret = self::$mMemcacheObj->set($wSessId, '', 0, SESS_LIFTTIME);

if (TRUE != $ret)
{
die("Fatal Error: Session ID $wSessId init failed!");

return FALSE;
}

return TRUE;
}
}
// }}}

/** {{{ sessWrite($wSessId, $wData)
*
* @param   String  $wSessId
* @param   String  $wData
*
* @return  Bool    TRUE/FALSE
*/
public function sessWrite($wSessId = '', $wData = '')
{
$ret = self::$mMemcacheObj->replace($wSessId, $wData, 0, SESS_LIFTTIME);

if (TRUE != $ret)
{
die("Fatal Error: SessionID $wSessId Save data failed!");

return FALSE;
}

return TRUE;
}
// }}}

/** {{{ sessDestroy($wSessId)
*
* @param   String  $wSessId
*
* @return  Bool    TRUE/FALSE
*/
public function sessDestroy($wSessId = '')
{
self::sessWrite($wSessId);

return FALSE;
}
// }}}

/** {{{ sessGc()
*
* @param   NULL
*
* @return  Bool    TRUE/FALSE
*/
public function sessGc()
{
//无需额外回收,memcache有自己的过期回收机制

return TRUE;
}
// }}}

/** {{{ initSess()
*
* @param   NULL
*
* @return  Bool    TRUE/FALSE
*/
public function initSess()
{
$domain = '.imysql.cn';

//不使用 GET/POST 变量方式
ini_set('session.use_trans_sid',    0);

//设置垃圾回收最大生存时间
ini_set('session.gc_maxlifetime',   SESS_LIFTTIME);

//使用 COOKIE 保存 SESSION ID 的方式
ini_set('session.use_cookies',      1);
ini_set('session.cookie_path',      '/');

//多主机共享保存 SESSION ID 的 COOKIE
ini_set('session.cookie_domain',    $domain);

//将 session.save_handler 设置为 user,而不是默认的 files
session_module_name('user');

//定义 SESSION 各项操作所对应的方法名:
session_set_save_handler(
array('MemacheSession', 'sessOpen'),   //对应于静态方法 My_Sess::open(),下同。
array('MemacheSession', 'sessClose'),
array('MemacheSession', 'sessRead'),
array('MemacheSession', 'sessWrite'),
array('MemacheSession', 'sessDestroy'),
array('MemacheSession', 'sessGc')
);

session_start();

return TRUE;
}
// }}}

}//end class

}//end define

$memSess    = new MemacheSession;
$memSess->initSess();
?>
然后,在项目程序的头文件中直接包含 MemacheSession.inc.php 即可,并且以前的程序不用做任何改动。

  特别感谢:黑夜路人 的 实现基于Memcache存储的Session类。

备注:memcache PECL 未来版本中,可以直接设置 php.ini 来这定自己的 session.save_handler,大致如下: 

Php代码  



session.save_handler = memcache  

session.save_path = "tcp://host:port?persistent=1&weight=2&timeout=2&retry_interval=15,tcp://host2:port2" 

1。安装memcached,ubuntu懒人方式当然首选 apt-get。apache php5 安装我就不多说了。 
apt-get install memcached php5-memcache
将etc/memcached.conf  中的 127.0.0.1 改成 服务器地址我这里是 192.168.1.105.可以给memcache 单建一个用户去跑服务,默认是nobody,我就不去建了。
将/etc/php5/apache2/conf.d/memcache.ini  里的 extension=memcache.so 前注释去掉。然后重启动apache2 查看 phpinfo 中的 "Registered save handlers" 会有 "files user memcache" 这3个可用。
2。然后修改 /etc/php5/apache2/php.ini
session.save_handler = memcache

session.save_path = "tcp://192.168.1.105:11211"
使用多个 memcached server 时用逗号","隔开
也可以在 .htaccess :
php_value session.save_handler "memcache"

php_value session.save_path  "tcp://192.168.1.105:11211"
再或者在某个一个应用中:
ini_set("session.save_handler", "memcache");
ini_set("session.save_path", "tcp://192.168.1.105:11211");

3.启动memcached

/etc/init.d/memcached start

4. 在程序中使用 memcache 来作 session 存储,用例子测试一下:
<?php
session_start();
if (!isset($_SESSION['TEST'])) {
$_SESSION['TEST'] = time();
}

$_SESSION['TEST3'] = time();

print $_SESSION['TEST'];
print "<br><br>";
print $_SESSION['TEST3'];
print "<br><br>";
print session_id();
?>
 
用 sessionid 去 memcached 里查询一下:
<?php
$memcache = memcache_connect('192.168.1.105', 11211);
var_dump($memcache->get('27f535433865c7e250d2d1062322edfd'));
?>
会有看到
string(37) "TEST|i:1219222593;TEST3|i:1219222611;"
这样的输出,证明session正常工作了。
 
web2 安装
apt-get install php5-memcache
然后修改/etc/php5/apache2/conf.d/memcache.ini 
将extension=memcache.so 前注释去掉。
然后修改/etc/php5/apache2/php.ini
session.save_handler = memcache
session.save_path = "tcp://192.168.1.105:11211"
同样可以用上面的例子做测试.
 
总结
用 memcache 来存储 session 在读写速度上会比 files 时快很多,
而且在多个服务器需要共用 session 时会比较方便,将这些服务器都配置
成使用同一组 memcached 服务器就可以,减少了额外的工作量。
缺点是 session 数据都保存在 memory 中,持久化方面有所欠缺,
但对 session 数据来说也不是很大的问题.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息