您的位置:首页技术文章
文章详情页

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

【字号: 日期:2022-09-13 11:40:40浏览:2作者:猪猪
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 memcacheEnable 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 = memcachesession.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 = memcachesession.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的散列算法分布的更加平均。

<?phpini_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进程进行测试

<?phpini_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都是同样的。

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

基于此点,

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

<?phpini_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分布保存。

标签: PHP
相关文章: