码迷,mamicode.com
首页 > 系统相关 > 详细

Memcached 笔记与总结(9)Memcached 与 Session

时间:2015-12-08 01:57:39      阅读:337      评论:0      收藏:0      [点我收藏+]

标签:

一、Memcached 存储 Session

由于 Memcached 是分布式的内存对象缓存系统,因此可以用来实现 Session 同步:把 Web 服务器中的内存组合起来,成为一个“内存池”,不管是哪个服务器产生的 Sessoin 都可以放到这个“内存池”中,其他的 Web 服务器都可以使用。使用 Memcached 来同步 Session 的优点是:不会加大数据库的负担,并且安全性比 Cookie 高,把 Session 放到内存里面,读取速度比其他处理方式要快很多。

自定义使用 Memcached 处理 Session 信息,要使用到用户自定义会话存储函数 session_set_save_handler() ,自定义的 Session 类可以参考 ThinkPHP 3.2.3 full 版中的 Session 类(\ThinkPHP\Library\Think\Session\Driver\Memcache.class.php)

 

注:使用的 php 扩展为 memcache 1.4.24,服务器环境为 Windows7 + PHP 5.3.10 + Apache 2.2.21

 

memcached.class.php

<?php

class MemcacheSession {

    protected static $lifeTime     = 3600;
    protected static $handle       = null;

    public function start(Memcache $mem) {
        self::$handle = $mem;
        self::$lifeTime = ini_get(‘session.gc_maxlifetime‘);
        session_set_save_handler(
            array(__CLASS__, ‘open‘),
            array(__CLASS__, ‘close‘),
            array(__CLASS__, ‘read‘),
            array(__CLASS__, ‘write‘),
            array(__CLASS__, ‘destroy‘),
            array(__CLASS__, ‘gc‘)
        );
        session_start();
    }

    /**
     * 打开Session 
     * @access private 
     * @param string $savePath 
     * @param mixed $sessName  
     */
    private static function open($savePath, $sessName) {
        return true;
    }

    /**
     * 关闭Session 
     * @access public 
     */
    public static function close() {
        self::gc(self::$lifeTime);
        self::$handle->close();
        self::$handle = null;
        return true;
    }

    /**
     * 读取Session 
     * @access private 
     * @param string $sessID 
     */
    private static function read($sessID) {
        return self::$handle->get($sessID);
    }

    /**
     * 写入Session 
     * @access public 
     * @param string $sessID 
     * @param String $sessData  
     */
    public static function write($sessID, $sessData) {
        return self::$handle->set($sessID, $sessData, 0, self::$lifeTime);
    }

    /**
     * 删除Session 
     * @access private 
     * @param string $sessID 
     */
    private static function destroy($sessID) {
        return self::$handle->delete($sessID);
    }

    /**
     * Session 垃圾回收
     * @access private 
     * @param string $sessMaxLifeTime 
     */
    private static function gc($sessMaxLifeTime) {
        return true;
    }  
}

 

使用 memcached.class.php

session.php

<?php
header(‘Content-type:text/html; charset=utf-8‘);

require ‘memcache.class.php‘;

$mem = new Memcache();
$mem->connect(‘127.0.0.1‘, 11211);

$memclass = new MemcacheSession();
$memclass->start($mem);

$_SESSION[‘username‘] = ‘dee‘;

echo ‘<a href="get.php" target="_blank">跳转</a>‘;

echo ‘<pre>‘; 
print_r($_SESSION); 
echo session_id(),‘<br />‘;

 

get.php

<?php

require ‘memcache.class.php‘;

$mem = new Memcache();
$mem->connect(‘127.0.0.1‘, 11211);

$memclass = new MemcacheSession();
$memclass->start($mem);

echo ‘<pre>‘;
print_r($_SESSION);
echo session_id();

 

 

二、Memcached 集群实现 Session 共享 

模拟开启两台 Memcached 服务器(127.0.0.1:11211 和 127.0.0.1:11212),引入 Memcached 的 Session 类, 同时修改 php.ini 中的配置

ini_set(‘memcache.hash_strategy‘, ‘consistent‘);//使用一致性hash算法
ini_set(‘session.save_path‘, ‘tcp://127.0.0.1:11211?weight=10,tcp://127.0.0.1:11212‘);

 

此时查看 phpinfo 的信息:

技术分享

 技术分享

 

设置 Session

cluster_session_set.php

<?php
header(‘Content-type:text/html; charset=utf-8‘);

require ‘memcache.class.php‘;

ini_set(‘memcache.hash_strategy‘, ‘consistent‘);
ini_set(‘session.save_path‘, ‘tcp://127.0.0.1:11211?weight=10,tcp://127.0.0.1:11212‘);

$mem = new Memcache();
$mem->addServer("127.0.0.1",11211) or die ("Could not add server 11211");  
$mem->addServer("127.0.0.1",11212) or die ("Could not add server 11212");  

$memclass = new MemcacheSession();
$memclass->start($mem);

$_SESSION[‘username‘] = "deathmask";  

echo session_id(); 
echo ‘<pre>‘;
print_r($_SESSION);
echo ‘<a href="cluster_session_get.php" target="_blank">跳转</a>‘;

输出:

技术分享

 

打印 Session

cluster_session_get.php

<?php

require ‘memcache.class.php‘;

ini_set(‘memcache.hash_strategy‘, ‘consistent‘);
ini_set(‘session.save_path‘, ‘tcp://127.0.0.1:11211?weight=10,tcp://127.0.0.1:11212‘);

$mem = new Memcache();
$mem->addServer("127.0.0.1",11211) or die ("Could not add server 11211");  
$mem->addServer("127.0.0.1",11212) or die ("Could not add server 11212");  

$memclass = new MemcacheSession();
$memclass->start($mem);

echo session_id(); 

echo ‘<pre>‘;
print_r($_SESSION);

输出:

技术分享

 

使用 telnet 客户端分别连接 127.0.0.1:11211 和 127.0.0.1:11212,获得 session_id 所对应的值:

技术分享

127.0.0.1:11211

 

技术分享

127.0.0.1:11212

 

 

三、Memcached 存储 Session 的弊端

① Memcached 把内存分成很多种规格的存储块(chunk),这种方式决定了 Memcached 不能完全利用内存,会产生内存碎片,如果存储块不足,还会产生内存溢出;

 

② 当 Memcached 集群发生故障(比如内存溢出)或者维护(比如升级、增加或减少服务器)时,用户会无法登录,或者被踢掉线;

 

③ Memcached 的回收机制(LRU,Least Recently Used 近期最少使用算法)可能会导致用户无缘无故地掉线。

 

解决方案是可以使用 Memcached + MySQL:

a. 当用户登录时,将 Session “set”到 Memcached,并写入数据库;

b. 在 Session 中增加一个字段,标识 Session 最后写入数据库的时间;

c. 每个页面加载的时候,优先从 Memcached 读取 Session,其次从数据库读取;

d. 每加载 N 页或者 Y 分钟后,再次将 Session 写入数据库;

e. 从数据库中获取过期 Session,优先从 Memcached 中获取最新数据

 

或者使用 Redeis ,利用 Redis 的持久化来存储 Session。

 

参考:

集群中用Memcached来实现session共享 

为什么不能用memcached存储Session

web集群时session同步的3种方法

如何严格设置php中session过期时间

利用memcached来做会话共享

Session变量不能传送到下一页.解决: session.use_trans_sid = 1

基于php使用memcache存储session的详解

php模块memcache和memcached区别分析

关于memcache分布式一致性hash

memcached 内存分配(slab和chunk)

Memcached 笔记与总结(9)Memcached 与 Session

标签:

原文地址:http://www.cnblogs.com/dee0912/p/4986627.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!