一、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('session.save_path', 'tcp://127.0.0.1:11211,tcp://127.0.0.1:11212');
ini_set('memcache.hash_strategy', 'consistent');//使用一致性分布式哈希
ini_set('memcache.hash_function','crc32');

此时查看 phpinfo 的信息(该页面需要使用 ini_set 设置配置信息):

设置 Session

cluster_session_set.php

<?php
header('Content-type:text/html; charset=utf-8'); require 'memcache.class.php'; ini_set('session.save_path', 'tcp://127.0.0.1:11211,tcp://127.0.0.1:11212');
ini_set('memcache.hash_strategy', 'consistent');
ini_set('memcache.hash_function','crc32'); $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";
$_SESSION['level'] = "admin"; 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('session.save_path', 'tcp://127.0.0.1:11211,tcp://127.0.0.1:11212');
ini_set('memcache.hash_strategy', 'consistent');
ini_set('memcache.hash_function','crc32'); $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);

输出:

测试过程:

a. 可以开启多个不同的浏览器,执行 cluster_session_set.php,则会生成多个会话。

注:打开 Memcached 服务器的方式为

-vvv 可以使错误信息或者警告信息在服务器端输出,便于调试

b. 使用 telnet 客户端分别连接两台 Memcached 服务器。

c. 使用浏览器一执行 cluster_session_set.php,生成的 PHPSESSID 是 02mn6pqd7d1vm5iseb3tq5irv2,被分配到了 127.0.0.1:11211 服务器

使用浏览器二执行页面,生成的 PHPSESSID 为 mktiotet1edifq7ttq2nbje480,被分配到了 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)

一致性hash算法在memcache集群中的应用

Memcached 笔记与总结(9)Memcached 与 Session的更多相关文章

  1. Memcached笔记——(三)Memcached使用总结

    为了将N个前端数据同步,通过Memcached完成数据打通,但带来了一些新问题: 使用iBatis整合了Memcached,iBatis针对每台server生成了唯一标识,导致同一份数据sql会产生不 ...

  2. Memcached笔记——(四)应对高并发攻击【转】

    http://snowolf.iteye.com/blog/1677495 近半个月过得很痛苦,主要是产品上线后,引来无数机器用户恶意攻击,不停的刷新产品各个服务入口,制造垃圾数据,消耗资源.他们的最 ...

  3. Memcached笔记——(四)应对高并发攻击

    近半个月过得很痛苦,主要是产品上线后,引来无数机器用户恶意攻击,不停的刷新产品各个服务入口,制造垃圾数据,消耗资源.他们的最好成绩,1秒钟可以并发6次,赶在Database入库前,Cache进行Mis ...

  4. Memcached笔记——(二)XMemcached&Spring集成

    今天研究Memcached的Java的Client,使用XMemcached 1.3.5,做个简单的测试,并介绍如何与Spring集成. 相关链接: Memcached笔记--(一)安装&常规 ...

  5. Memcached笔记——(一)安装&常规错误&监控

    08年的时候接触过Memcached,当时还对它的客户端产品嗤之以鼻,毕竟手工代码没有各种ORM原生XML配置方便.尽管如此,Memcached现在已经成了服务器架构里不可或缺的一部分! 相关链接: ...

  6. Key/Value之王Memcached初探:三、Memcached解决Session的分布式存储场景的应用

    一.高可用的Session服务器场景简介 1.1 应用服务器的无状态特性 应用层服务器(这里一般指Web服务器)处理网站应用的业务逻辑,应用的一个最显著的特点是:应用的无状态性. PS:提到无状态特性 ...

  7. PHP如何将session保存到memcached中?如何分布式保存PHP session

    session_set_save_handler无关的memcached保存session的方法 在memcached服务器上 1)下载memcached #wget http://memcached ...

  8. 【转】 Key/Value之王Memcached初探:三、Memcached解决Session的分布式存储场景的应用

    一.高可用的Session服务器场景简介 1.1 应用服务器的无状态特性 应用层服务器(这里一般指Web服务器)处理网站应用的业务逻辑,应用的一个最显著的特点是:应用的无状态性. PS:提到无状态特性 ...

  9. Memcached 笔记与总结(8)Memcached 的普通哈希分布算法和一致性哈希分布算法命中率对比

    准备工作: ① 配置文件 config.php ② 封装 Memcached 类 hash.class.php,包含普通哈希算法(取模)和一致性哈希算法 ③ 初始化 Memcached 节点信息 in ...

  10. Memcached 笔记与总结(7)增加虚拟节点

    仅仅把 Memcached 服务器集群地址通过一致性哈希转映射在圆环上,可能会出现数据不能均匀地分配给各台 Memcached 服务器. 解决方案是引入虚拟节点,就是把每个映射在圆环上的服务器地址(物 ...

随机推荐

  1. How to retrieve instance parameters from an uninstantiated (uninserted) family

    The trick to be able to read the default values for instance parameters is to get to the FamilyManag ...

  2. Excel 如何引用某表格中的某一列作为数据有效性验证

    1. 首先把数据有效性的列表加入到某个表格中.如下图所示:此表格名称为表5 2. 然后定义名称:公式--定义名称 如下填入信息: 3. 然后再数据有效性验证中输入如下信息即可:

  3. POJ 1845 (约数和+二分等比数列求和)

    题目链接: http://poj.org/problem?id=1845 题目大意:A^B的所有约数和,mod 9901. 解题思路: ①整数唯一分解定理: 一个整数A一定能被分成:A=(P1^K1) ...

  4. doPost方法与doGet方法

    例子我们发现forward跳转访问Servlet说不定的感觉,其实我们要想弄明白这个问题,就要从forward本身来研究了. 我们都知道 forward跳转是转发请求,不转发地址的,简单点说,forw ...

  5. 被解放的GPU CSS3动画加速

    概念 图形处理器( Graphics Processing Unit ) 专门用来处理在个人电脑.工作站或游戏机上图像运算工作 显卡的“心脏” 90%以上的新型台式电脑和笔记本型电脑拥有集成图形处理器 ...

  6. ACM 擅长排列的小明

    擅长排列的小明 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 小明十分聪明,而且十分擅长排列计算.比如给小明一个数字5,他能立刻给出1-5按字典序的全排列,如果你想 ...

  7. 【BZOJ】3676: [Apio2014]回文串

    http://www.lydsy.com/JudgeOnline/problem.php?id=3676 题意:给一个串求回文串×出现次数的最大值.(|S|<=300000) #include ...

  8. 【BZOJ】2456: mode

    http://www.lydsy.com/JudgeOnline/problem.php?id=2456 题意:给一个$n<=500000$的数列,求出现次数超过$\lfloor \frac{n ...

  9. 【BZOJ1968】【AHoi2005】COMMON约数研究

    Description Input 只有一行一个整数 N(0 < N < 1000000). Output 只有一行输出,为整数M,即f(1)到f(N)的累加和. Sample Input ...

  10. POJ 1564 经典dfs

    1.POJ 1564 Sum It Up 2.总结: 题意:在n个数里输出所有相加为t的情况. #include<iostream> #include<cstring> #in ...