一相关介绍
1.memcache + memcache的多服务器数据共享的介绍,请参见http://www.guigui8.com/index.php/archives/206.html
2.session机制:
session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。
当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识- 称为sessionid,如果已包含一个sessionid则说明以前已经为此客户端创建过session,服务器就按照sessionid把这个session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含sessionid,则为此客户端创建一个session并且生成一个与此session相关联的sessionid,sessionid的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个sessionid将被在本次响应中返回给客户端保存。
保存这个sessionid的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发挥给服务器。
一般这个cookie的名字都是类似于SEEESIONID,而。比如weblogic对于web应用程序生成的cookie,PHPSESSID=ByOK3vjFD75aPnrF3K2HmdnV6QZcEbzWoWiBYEnLerj,它的名字就是PHPSESSID。
二动机
在实际web生产环境中,一个应用系统,往往将不同的业务应用分布到不同服务器上进行处理。
当跟踪当前在线用户信息时,如果是同一个主域名时,可以用全域cookie处理相关数据的共享问题;如果是在不同主域下,则可以通过观察者模式的中心话概念解决相应问题,通过这种概念延伸出的解决方案有很多,而今天我所要讲的,是前一种,通过memcache的多服务器数据共享技术来模拟session,以进行对当前在线用户数据的多服务器共享。
关于多服务器统一session信息,要求如下:
1.能够在memcached规定的几台服务器上,保存session信息(通过前面介绍的memcache的多服务器数据共享);
2.能够象zend定义的session_start()前,通过session_id($sessid)那样,自定义session_id的值。
3.能方便的在系统运行时,切换memcached存储的session信息和 用文件存储的session信息的操作。
三代码
实现方式很简单,通过memcache来模拟session机制,只是利用memcache将存储媒介换成共享服务器的内存,以达到多台分布式部署的服务器共享session信息的目的。而调用的接口,与zend提供的session操作函数相区别,所以可以方便的在memcache和文件的session信息操作建切换。
以下代码,已经过多次实际测试,能达到以上功能需求。先贴下面了:
复制代码 代码如下:
class MemcacheSession
{
// {{{ 类成员属性定义
public $memObject = null; //memcache操作对象句柄
private $_sessId = '';
private $_sessKeyPrefix = 'sess_';
private $_sessExpireTime = 86400;
private $_cookieDomain = '.guigui8.com'; //全域cookie域名
private $_cookieName = '_PROJECT_MEMCACHE_SESS';
private $_cookieExpireTime = '';
private $_memServers = array('192.168.0.3' => 11211, '192.168.0.4' => 11211);
private $_sessContainer = array(); //当前用户的session信息
private static $_instance = null; //本类单例对象
// }}}
public static function getInstance($host='', $port=11211, $isInit = true) {
if (null === self::$_instance) {
self::$_instance = new self($host, $port, $isInit);
}
return self::$_instance;
}
private function __construct($host='', $port=11211, $isInit = false){
!empty($host) && $this->_memServers = array(trim($host) => $port);
$isInit && $this->start();
}
public function start($expireTime = 0){
$_sessId = $_cookie[$this->_cookieName];
if (!$_sessId){
$this->_sessId = $this->_getId();
$this->_cookieExpireTime = ($expireTime > 0) ? time() + $expireTime : 0;
setcookie($this->_cookieName, $this->_sessId, $this->_cookieExpireTime, "/", $this->_cookieDomain);
$this->_initMemcacheObj();
$this->_sessContainer = array();
$this->_saveSession();
} else {
$this->_sessId = $_sessId;
$this->_sessContainer = $this->_getSession($_sessId);
}
}
public function setSessId($sess_id){
$_sessId = trim($sess_id);
if (!$_sessId){
return false;
} else {
$this->_sessId = $_sessId;
$this->_sessContainer = $this->_getSession($_sessId);
}
}
public function isRegistered($varName){
if (!isset($this->_sessContainer[$varName])){
return false;
}
return true;
}
public function set($varName, $varValue){
$this->_sessContainer[$varName] = $varValue;
$this->_saveSession();
return true;
}
public function get($varName){
if (!isset($this->_sessContainer[$varName])){
return false;
}
return $this->_sessContainer[$varName];
}
public function delete($varName){
unset($this->_sessContainer[$varName]);
$this->_saveSession();
return true;
}
public function destroy(){
$this->_sessContainer = array();
$this->_saveSession();
return true;
}
public function getAll(){
return $this->_sessContainer;
}
public function getSid(){
return $this->_sessId;
}
public function getMemServers(){
return $this->_memServers;
}
public function setMemServers($arr){
$this->_memServers = $arr;
}
public function addMemServer($host, $port){
$this->_memServers[trim($host)] = trim($port);
$this->memObject->addServer($host, $port);
}
public function removeMemServer($host){
unset($this->_memServers[trim($host)]);
}
private function _getId(){
return md5(uniqid(microtime()));
}
private function _getSessKey($_sessId = ''){
$sessKey = ($_sessId == '') ? $this->_sessKeyPrefix.$this->_sessId : $this->_sessKeyPrefix.$_sessId;
return $sessKey;
}
private function _initMemcacheObj(){
if (!class_exists('Memcache') || !function_exists('memcache_connect')){
$this->_showMessage('Failed: Memcache extension not install, please from http://pecl.php.net download and install');
}
if ($this->memObject && is_object($this->memObject)){
return true;
}
$this->memObject = new Memcache;
if (!empty($this->_memServers)) {
foreach ($this->_memServers as $_host => $_port) {
$this->memObject->addServer($_host, $_port);
}
}
return true;
}
private function _getSession($_sessId = ''){
$this->_initMemcacheObj();
$sessKey = $this->_getSessKey($_sessId);
$sessData = $this->memObject->get($sessKey);
if (!is_array($sessData) || empty($sessData)){
//this must be $_cookie['__SessHandler'] error!
return array();
}
return $sessData;
}
private function _saveSession($_sessId = ''){
$this->_initMemcacheObj();
$sessKey = $this->_getSessKey($_sessId);
if (empty($this->_sessContainer)){
$ret = @$this->memObject->set($sessKey, $this->_sessContainer, false, $this->_sessExpireTime);
}else{
$ret = @$this->memObject->replace($sessKey, $this->_sessContainer, false, $this->_sessExpireTime);
}
if (!$ret){
$this->_showMessage('Failed: Save sessiont data failed, please check memcache server');
}
return true;
}
private function _showMessage($strMessage, $isFailed = true){
return;
if ($isFailed){
echo ($strMessage);
}
echo $strMessage;
}
四应用
1.本地session存储,与原始session操作方式一样,没有任何改变。如:
复制代码 代码如下:
session_start();
$_SESSION['file_session_info']= '本地文件保存的session信息'; //本地文件保存的session
2.memcache共享服务器的session存储
复制代码 代码如下:
$mem= MemcacheSession::getInstance('192.168.0.4', 11211);
$mem->addMemServer('192.168.0.4',11211);
$mem->addMemServer('192.168.0.5',11211);
//如果cookie功能不可用,则根据其他参数传递的唯一信息,设置映射为session_id
if(1) {
$sn= '838ece1033bf7c7468e873e79ba2a3ec';
$mem->setSessId($sn);
}
$mem->set('name','guigui'); //多台memcache服务器共享的session
$mem->set('addr','wuhan'); //多台memcache服务器共享的session
//$mem->destroy();
3.分别获取本地和memcache存储的session信息
复制代码 代码如下:
$addr= $mem->get('addr');
$_MEM_SESSION= $mem->getAll();
echo"
localhost file session:";
var_dump($_SESSION);
echo"
memcache session:";
var_dump($_MEM_SESSION);
//$res= $mem->delete('name');



