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

来源:互联网 发布:股市手机交易软件 编辑:程序博客网 时间:2024/05/22 17:43
再自定义一套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,大致如下:

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 存储,用例子测试一下:
<?phpsession_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 = memcachesession.save_path = "tcp://192.168.1.105:11211"
同样可以用上面的例子做测试.
 
总结
用 memcache 来存储 session 在读写速度上会比 files 时快很多,
而且在多个服务器需要共用 session 时会比较方便,将这些服务器都配置
成使用同一组 memcached 服务器就可以,减少了额外的工作量。
缺点是 session 数据都保存在 memory 中,持久化方面有所欠缺,
但对 session 数据来说也不是很大的问题.


原创粉丝点击