PHP如何将session保存到memcached中?如何分布式保存PHP session
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的散列算法分布的更加平均。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <?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进程进行测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <?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都是同样的。
这就导致了两个文件中的内容一致而另一个文件中没有内容,
基于此点,
我只能分次调用脚本,脚本修改如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <?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中的方法
【CSDN】PHP + Memcache 实现多服务器session共享
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步