+ -
当前位置:首页 → 问答吧 → 基于Memcache的 Session数据的多服务器共享(二)

基于Memcache的 Session数据的多服务器共享(二)

时间:2009-05-24

来源:互联网

本帖最后由 evangui 于 2009-5-24 16:56 编辑

来源:http://www.guigui8.com/index.php/archives/214.html(转载请注明出处)

一 简介

前面《基于Memcache的 Session数据的多服务器共享(一)》一文,介绍了在全域情况下,进行多台分布式服务器进行共享session的处理;本篇则探讨一种通用的多服务器共享session的处理方法。

如果是只需要用memcache来存储session, 则也没什么必要写这篇文章,因为zend的session处理策略已经很完美的支持memcache方式。
而本文介绍的方法,主要是利用切换session环境的初始设置,来达到memcache和文件读写session的切换。

二  相关说明

session_write_close这个函数,在这里起着至关重要的作用。直接把manual的定义贴在下面

session_write_close
(PHP 4 >= 4.0.4, PHP 5)

session_write_close — Write session data and end session
Description
void session_write_close ( void )

End the current session and store session data.

Session data is usually stored after your script terminated without the need to call session_write_close(), but as session data is locked to prevent concurrent writes only one script may operate on a session at any time. When using framesets together with sessions you will experience the frames loading one by one due to this locking. You can reduce the time needed to load all the frames by ending the session as soon as all changes to session variables are done.

这个函数,在本blog另一篇文章 《PHP版单点登陆实现方案》 里有大量应用。在此就不深入说明。

三 代码

代码没有经过深入测试,只是提供思路。
[php]<?php
/**
*=---------------------------------------------------------------------------=
*                         SessionMgr.class.php
*=---------------------------------------------------------------------------=
*
* 利用memcache进行session存储服务。
*
* Copyright(c) 2008 by guigui. All rights reserved.
* @author guigui <[email protected]>
* @version $Id: SessionMgr.class.php, v 1.0 2008/10/7 $
* @package systen
* @link http://www.guigui8.com/index.php/archives/214.html
*/

/**
* SessionMgr类
*
* 用于提供利用memcache进行session存储服务的功能
*/
class SessionMgr
{
    // {{{ 类成员属性定义
    /**
     * 用memcache进行session处理时,当前用户的session id值
     *
     * @var string
     */
    private static $_memSessId = null;

    /**
     * 用文件进行session处理时,当前用户的session id值
     *
     * @var string
     */
    private static $_fileSessId = null;

    /**
     * 当前使用的session策略
     *
     * @var string
     */
    private static $_currentStrategy = 'mem';

    /**
     * session内容保存的路径
     * (这里通过zend提供的memcache存储session的方式,进行配置)
     *
     * @var unknown_type
     */
    private static $_sessionSavePath = "tcp://192.168.0.2:11211?persistent=1&weight=2&timeout=2&retry_interval=10";
    // }}}

    /**
     *=-----------------------------------------------------------------------=
     *=-----------------------------------------------------------------------=
    *            Public Methods
     *=-----------------------------------------------------------------------=
     *=-----------------------------------------------------------------------=
     */

    /**
     * 设置session数据的存储路径(memcache和文件通用)
     *
     * 通常这个用于memcache共享服务器 设置初始化处理。
     *
     * @param string $session_save_path   - memcache数据存储的服务器ip
     */
    public static function setSessionSavePath($session_save_path) {
        self::$_sessionSavePath = $session_save_path;
    }

    /**
     * 获取当前使用的session策略(mem或file)
     *
     * @return string $_currentStrategy   - 当前使用的session策略
     */
    public static function getSessionStrategy() {
        return self::$_currentStrategy;
    }

    /**
     * session处理的初始化操作
     *
     */
    static private function _init() {
        session_write_close();
        ini_set('session.auto_start', 0);
        ini_set('session.cookie_lifetime',  0);
        ini_set('session.gc_maxlifetime',   3600);
    }

    /**
     * 同session_id()的功能,只是提供给文件session
     *
     * @param string $session_id   - 可选参数
     * @return string              - 当前使用的session id
     */
    public static function fileSessionId($session_id=null) {
        self::_init();
        ini_set('session.save_handler', 'files');

        if (null === $session_id) {
            self::$_fileSessId = session_id();
        } else {
            session_id($session_id);
            self::$_fileSessId = $session_id;
        }
        return self::$_fileSessId;
    }

    /**
     * 同session_start()的功能
     *
     */
    public static function fileSessionStart() {
        if (null === self::$_fileSessId) {
            self::fileSessionId();
        }
        session_start();
        self::$_currentStrategy = 'file';
    }

    /**
     * 立即切换到文件session的方式
     *
     */
    public static function trans2fileSession() {
        self::fileSessionId(self::$_fileSessId);
        self::fileSessionStart();
    }

    /**
     * 同session_id()的功能,只是提供给memcache session使用
     *
     * @param string $session_id   - 可选参数
     * @return string              - 当前使用的session id
     */
    public static function memSessionId($session_id=null) {
        self::_init();
        ini_set('session.save_handler', 'memcache');
        ini_set('session.save_path', self::$_sessionSavePath);

        if (null === $session_id) {
            self::$_memSessId = session_id();
        } else {
            session_id($session_id);
            self::$_memSessId = $session_id;
        }
        return self::$_memSessId;
    }

    /**
     * 同session_start()的功能
     *
     */
    public static function memSessionStart() {
        if (null === self::$_memSessId) {
            self::memSessionId();
        }

        session_start();
        self::$_currentStrategy = 'mem';
    }

    /**
     * 立即切换到memcache的session的方式
     *
     */
    public static function trans2memSession() {
        self::memSessionId(self::$_memSessId);
        self::memSessionStart();
    }

    /**
     * 在memcache共享服务器的设置 中 增加一台服务器也用于共享数据的存储
     * (设置会立即生效)
     *
     */
    public static function addServer($host, $port = '11211') {
        $host = trim($host);
        $port = trim($port);
        self::$_sessionSavePath .= ",tcp://$host:$port";
        self::trans2memSession();
    }

    /**
     * 在memcache共享服务器的设置 中 移除一台服务器用于共享数据的存储
     * (设置会立即生效)
     *
     */
    public static function removeServer($host) {
        $host = trim($host);
        $_save_path = explode(',', self::$_sessionSavePath);
        foreach ($_save_path as $key => $val) {
            $_server_arr = explode(':', $val);
            if ($_server_arr[0] == "tcp://$host") {
                unset($_save_path[$key]);
                break;
            }
            continue;
        }
        self::$_sessionSavePath = implode(',', $_save_path);
        self::trans2memSession();
    }


}//end class
?>[/php]

四 使用

1. 设置memcache的session存储变量

[php]SessionMgr::memSessionStart();
$_SESSION['memcache_key1'] = array(
    'param1' => '11111',
    'param2' => '22222'
);[/php]

2. 设置文件的session存储变量
[php]
SessionMgr::trans2fileSession();
$_SESSION['file_key1'] = array(
    'param1' => 'aaaaa',
    'param2' => 'bbbbb'
);
[/php]

3. 设置memcache的session存储变量
[php]
SessionMgr::trans2memSession();
$_SESSION['memcache_key2'] = array(
    'param1' => '33333',
    'param2' => '44444'
);
[/php]

注意区分当前session策略(可以通过SessionMgr::getSessionStrategy()来查看)
4. 获取memcache的session存储变量


if ('mem' === SessionMgr::getSessionStrategy()) {
    var_dump($_SESSION);
} else {
    SessionMgr::trans2memSession();
    var_dump($_SESSION);
}



5. 获取file的session存储变量


if ('file' === SessionMgr::getSessionStrategy()) {
    var_dump($_SESSION);
} else {
    SessionMgr::trans2fileSession();
    var_dump($_SESSION);
}

来源:http://www.guigui8.com/index.php/archives/214.html

作者: evangui   发布时间: 2009-05-24

支持,memcache真是好东西

作者: lxylxy888666   发布时间: 2009-05-24

辛苦了

作者: 一中   发布时间: 2009-05-25