session_set_save_handler无关的memcached保存session的方法

在memcached服务器上

1)下载memcached

#wget http://memcached.googlecode.com/files/memcached-1.4.15.tar.gz

2)由于memcached依赖libevent所以需要先安装libevent库,这里直接yum安装

#yum install *libevent*

3)安装memcached

#./configure --prefix=/usr/local/memcached
#make
#make install

4)启动memcached

#/usr/local/memcached/bin/memcached -d -m 4096 -p 11211 -u root
-d daemon ?-p port -u ?user -m memory

在web server服务器上

5)在web server上安装php的memcache模块

#/usr/local/php/bin/pecl install memcache

Enable memcache session handler support? [yes] : yes(这里选择yes)

6)在php.ini中加入如下内容:

extension=/usr/local/php/lib/php/extensions/no-debug-non-zts-20090626/memcache.so

7)修改php.ini中的session.save_handler及session.save_path为如下内容:

session.save_handler = memcache
session.save_path = "tcp://memcached服务器ip:11211"

亦可在PHP程序中

ini_set('session.save_handler', 'memcache');
ini_set('session.save_path', 'tcp://memcached服务器ip:11211');

注意:这种使用memcached保存session的方式与session_set_save_handler无关


安装完memcached之后

在php.ini中

将session.save_handler 修改为memcache,并修改save_path指向memcached的地址和端口即可

session.save_handler = memcache
session.save_path = tcp://127.0.0.1:11211

memcache的PECL这个扩展非常强大,可以支持failover以及分布存储。

使用方法很简单,只需要在session.save_path的参数列表中,使用逗号分隔各个memcached服务器,如:

session.save_path = "tcp://172.16.8.81:11211,tcp://172.16.8.82:11211,tcp://172.16.8.83:11211"

则保存的session会经过hash之后保存到各个memcached服务器中,而hash的算法memcache支持两种,crc32以及fnv:

memcache.hash_function= {crc32,fnv}

文档中很少有提到fnv算法的,据说其散列要比crc32更好,但是我通过以下小小的程序实验之后,发现仍旧是crc32的散列算法分布的更加平均。

<?php
ini_set("memcache.hash_function", "crc32");
$memcache = new Memcache;
$memcache1 = new Memcache;
$memcache2 = new Memcache;
$memcache->addServer('localhost', 11211);
$memcache->addServer('localhost', 11212);
$memcache->flush();
$memcache1->connect('localhost', 11211);
$memcache2->connect('localhost', 11212);
$fp1 = fopen("mem1.txt", "w");
$fp2 = fopen("mem2.txt", "w");
for ($i = 0; $i < 1000; $i++)
{
$memcache->set($i, $i, 0, 1000);
fwrite($fp1, $memcache1->get($i) . " ");
fwrite($fp2, $memcache2->get($i) . " ");
}
fclose($fp1);
fclose($fp2);

接着我就session的保存进行了测试

我开了3个memcached进程进行测试

<?php
ini_set("memcache.hash_function", "fnv");
ini_set("error_reporting", "E_CORE_ERROR");
$memcache1 = new Memcache;
$memcache1->connect('localhost', 11211);
$memcache1->flush();
$memcache2 = new Memcache;
$memcache2->connect('localhost', 11212);
$memcache2->flush();
$memcache3 = new Memcache;
$memcache3->connect('localhost', 11213);
$memcache3->flush();
$fp1 = fopen('mem1.txt', 'w');
$fp2 = fopen('mem2.txt', 'w');
$fp3 = fopen('mem3.txt', 'w');
for ($i = 0; $i < 1000; $i++)
{
session_start();
$ssid = session_id();
echo $ssid;
session_register("id");
$_SESSION["id"] = $ssid;
session_write_close();
fwrite($fp1, $memcache1->get($ssid) . ' ');
fwrite($fp2, $memcache2->get($ssid) . ' ');
fwrite($fp3, $memcache3->get($ssid) . ' ');
//session_destroy();
}
fclose($fp1);
fclose($fp2);
fclose($fp3);

比较奇怪的是 memcached2一般都会不被选中,

而1,3的内容是一致的。可能是为了failover,

而当我把1,3关闭后,2中将会出现内容,说明memcached2是正常工作的。

而不论我的散列算法使用crc32还是fnv,这种现象都存在,

最后我发现:这个测试程序存在问题。

因为在session_write_close之后,整个程序的session都是唯一的了。

也就是虽然循环了这么多次,里面包含了session_destroy调用,但是返回的session id都是同样的。

这就导致了两个文件中的内容一致而另一个文件中没有内容,

基于此点,

我只能分次调用脚本,脚本修改如下:

<?php
ini_set("memcache.hash_strategy", "consistent");
ini_set("memcache.hash_function", "crc32");
ini_set("error_reporting", "E_CORE_ERROR");
ini_set("memcache.allow_failover", "0");
$memcache1 = new Memcache;
$memcache1->connect('localhost', 10001);
$memcache1->flush();
$memcache2 = new Memcache;
$memcache2->connect('localhost', 10002);
$memcache2->flush();
$memcache3 = new Memcache;
$memcache3->connect('localhost', 10003);
$memcache3->flush();
$fp1 = fopen("mem1.txt", "a+");
$fp2 = fopen("mem2.txt", "a+");
$fp3 = fopen("mem3.txt", "a+");
session_start();
$ssid = session_id();
echo $ssid . "\n";
session_register("id");
$_SESSION["id"] = $ssid;
//session_destroy();
session_write_close();
fwrite($fp1, $memcache1->get($ssid) . " ");
fwrite($fp2, $memcache2->get($ssid) . " ");
fwrite($fp3, $memcache3->get($ssid) . " ");
session_destroy();
fclose($fp1);
fclose($fp2);
fclose($fp3);

然后再shell中重复运行多次,返回的ID不同了。

再打开mem*.txt文件查看,

发现3个文件中,每个session会保存在其中两个文件,然后分布不同。

这证明了使用memcache来保存session,一个是做到了failover,第二会按照session id来做hash分布保存。

【51CTO博文】扫盲:php session缓存至memcached中的方法

CSDNPHP + Memcache 实现多服务器session共享

延伸阅读利用session_set_save_handler()函数将session保存到MySQL数据库中

Memcache学习总结.pdf

PHP如何将session保存到memcached中?如何分布式保存PHP session的更多相关文章

  1. Flask实战第43天:把图片验证码和短信验证码保存到memcached中

    前面我们已经获取到图片验证码和短信验证码,但是我们还没有把它们保存起来.同样的,我们和之前的邮箱验证码一样,保存到memcached中 编辑commom.vews.py .. from utils i ...

  2. Asp.net Session 保存到MySql中

    一 网站项目引入"mysql.web.dll" 二 web.config配置中添加mysql数据库连接字符串 <connectionStrings> <remov ...

  3. 利用session_set_save_handler()函数将session保存到MySQL数据库中

    PHP保存session默认的是采用的文件的方式来保存的,这仅仅在文件的空间开销很小的windows上是可以采用的,但是如果我们采用uinx或者是liux上的文件系统的时候,这样的文件系统的文件空间开 ...

  4. php session保存到memcache或者memcached中

    本教程叫你如何将php 的session存储在 memcached中,参考了好多网页,发现错误百出,最后自己还是测试成功了,现在将结果结果分享. 1-)系统环境 : elastix2.4 (cento ...

  5. ffmpeg从AVFrame取出yuv数据到保存到char*中

    ffmpeg从AVFrame取出yuv数据到保存到char*中   很多人一直不知道怎么利用ffmpeg从AVFrame取出yuv数据到保存到char*中,下面代码将yuv420p和yuv422p的数 ...

  6. [redis] session 保存到 redis 简单实现

    参考资料: [session保存到redis简单实现]http://blog.csdn.net/ppt0501/article/details/46700221 [Redis学习]http://blo ...

  7. 将数字n转换为字符串并保存到s中

    将数字n转换为字符串并保存到s中 参考 C程序设计语言 #include <stdio.h> #include <string.h> //reverse函数: 倒置字符串s中各 ...

  8. Android把图片保存到SQLite中

    1.bitmap保存到SQLite 中 数据格式:Blob db.execSQL("Create table " + TABLE_NAME + "( _id INTEGE ...

  9. c# 抓取和解析网页,并将table数据保存到datatable中(其他格式也可以,自己去修改)

    使用HtmlAgilityPack 基础请参考这篇博客:https://www.cnblogs.com/fishyues/p/10232822.html 下面是根据抓取的页面string 来解析并保存 ...

随机推荐

  1. px,em,rem

    px:像素是相对于显示器屏幕分辨率而言的相对长度单位.pc端使用px倒也无所谓,可是在移动端,因为手机分辨率种类颇多,不可能一个个去适配,这时px就显得非常无力,所以就要考虑em和rem. em:继承 ...

  2. 十连测Day1 题解

    A. 奥义商店 有一个商店,n个物品,每个物品有一个价格和一种颜色. 有m个操作,操作有两种,一种是修改一个位置的价格,另一种是购买,每次购买指定一个公差d和一个位置k,找到包含这个位置k公差为d的同 ...

  3. Vue2.0学习笔记一 :各种表达式

    #,过滤器 #,在Vue2.x中,过滤器只能在mustache绑定中使用,为了在指令帮定中实现同样的行为,你应该使用计算属性:     #,过滤器可以串联 {{ message | filterA | ...

  4. Javascript execCommon

    http://blog.csdn.net/woshinia/article/details/18664903 https://developer.mozilla.org/zh-CN/docs/Web/ ...

  5. linux命令总结

    vmstat: linux监控命令,可以展现服务器状态值. 一般vmstat工具的使用是通过两个数字参数来完成的,第一个是采样的时间间隔,单位是秒,第二参数是采样的次数 例:vmstat 3 2  ( ...

  6. python 小练手

    监控 主动监控 - 服务器端轮询客户端 被动监控-客户端agent上报到服务器端 混合模式---两种都支持 需求 1个性化的监控需求 2每个服务的监控间隔不同 3混合模式的监控

  7. Adapter的封装之路

    原文:Adapter的封装之路 一.几种常见列表效果: 假如要用RecyclerView实现下面的几种效果,你会如何实现呢? 效果1:单布局效果   效果2:多布局效果 有多种Item布局   效果3 ...

  8. Don’t Use Accessor Methods in Initializer Methods and dealloc 【初始化和dealloc方法中不要调用属性的存取方法,而要直接调用 _实例变量】

    1.问题:    在dealloc方法中使用[self.xxx release]和[xxx release]的区别? 用Xcode的Analyze分析我的Project,会列出一堆如下的提示:Inco ...

  9. import第三方库的头文件找不到的错误

    问题描述:使用cocoapods导入了第三方库,import该第三方库的某个头文件,然后编译报错找不到这个头文件内所import的头文件. 产生原因:我们需要配置头文件的搜索路径,告诉系统头文件的路径 ...

  10. [分类算法] :朴素贝叶斯 NaiveBayes

    1. 原理和理论基础(参考) 2. Spark代码实例: 1)windows 单机 import org.apache.spark.mllib.classification.NaiveBayes im ...