一、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. BZOJ 3282 Tree ——KD-Tree

    [题目分析] 明显的LCT维护连通性的题目. access的操作是比较巧妙的,可以把结点到根变成偏爱路径,而且保证了该点是链上深度最深的点. 而且需边的思想也很巧妙,保证了复杂度. 但是只能用于修改路 ...

  2. Middleware In ASP.NET Core

    中间件简介 ASP.NET Core 由很多中间件构成,实现了一个HTTP请求管道(pipeline). Request的Response的管道可以看成一个Push Stack 和 Pop Stack ...

  3. oracle查看表实际物理空间使用大小

    http://www.2cto.com/database/201107/95313.html 一种是分配给一个表的物理空间数量,而不管空间是否被使用.可以这样查询获得字节数:select segmen ...

  4. BZOJ4573 : [Zjoi2016]大森林

    扫描线,从左到右依次处理每棵树. 用set按时间顺序维护影响了这棵树的所有操作,那么一个点的父亲就是它前面第一个操作1. 用Splay维护树的括号序列,那么两点间的距离就是括号数量减去匹配的括号个数. ...

  5. nodejs express template (模版)的使用 (ejs + express)

    var app=require("express").createServer(); app.set("view engine","ejs" ...

  6. ACM 喷水装置(二)

    喷水装置(二) 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的 ...

  7. ACM 寻找最大数

    寻找最大数 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 请在整数 n 中删除m个数字, 使得余下的数字按原次序组成的新数最大, 比如当n=920813467185 ...

  8. 51Nod 1079 中国剩余定理 Label:数论

    一个正整数K,给出K Mod 一些质数的结果,求符合条件的最小的K.例如,K % 2 = 1, K % 3 = 2, K % 5 = 3.符合条件的最小的K = 23.   Input 第1行:1个数 ...

  9. jquery 动画效果插件

    从jQuery API 文档中可以知道,jQuery自定义动画的函数.animate( properties [, duration] [, easing] [, complete] )有四个参数: ...

  10. 【BZOJ】2938: [Poi2000]病毒

    题意 \(n\)个01病毒串,总长不超过\(30000\).问是否存在无限长的不包含病毒串的01串. 分析 考虑ac自动机,如果不包含病毒串而且无限长也就是说存在一个环(转移和fail树),使得环上不 ...