一直以来,由于php本身的session机制不能跨机,令很多phper感到不爽,现在流行的解决方案主要有:
1)使用数据库来实现
2)自己写server端,通过改写session处理函数来请求
3)使用nfs等跨机存储来保存session
4)使用memcache来保存
5)使用zend platform提供的解决方案
其中的1-4都是通过改用可以跨机的储存机制,再使用session_set_save_handler()来实现,5是zend公司的商业产品(不过据之前在使用的同事反映,效果不太满意),以上的方案,各有利弊,不在本文讨论范围
无论是用memcache,还是db,nfs,其原理是一样的,都是通过session_set_save_handler函数来改变默认的处理方式,通过指定回调函数来自定义处理,可以参考手册的session_set_save_handler()函数部分,有例子,比较容易明白
以下是一些我在使用memcache来实现时的一些记录:
1)使用类来实现时,各回调函数都定义为静态方法,在类的构造中使用session_set_save_handler注册回调函数, 如:
session_set_save_handler(
array(\'memSession\', \'open\'),
array(\'memSession\', \'close\'),
array(\'memSession\', \'read\'),
array(\'memSession\', \'write\'),
array(\'memSession\', \'destroy\'),
array(\'memSession\', \'gc\')
);
memSession为类名,要使用session,则先new memSession,再session_start();
2)生存期和垃圾回收
memCache的set命令有生存期,即使用set命令添加值时,可加上lifetime,此时间可以作为session的生存期,用户在此时间内没有动作,则会失效,但有动作则不会失效(因为每一个脚本结束时,都会执行write和close,此时lifetime就会被更新了),当然,如果使用cookie传递SID,则控制SESSION生存期可以用:ini_set(\'session.cookie_lifetime\',time)来设定,这其实是控制cookie的有效时间,如果session赖以生存的cookie消失了,当然session也就活不了,使用cookie_lifetime来控制的话,无论有无动作,都将在指定的时间后过时
gc是指垃圾回收,在session中是指清理过期的session数据,影响的参数有:
session.gc_maxlifetime 被视为垃圾前的生存期,超过此时间没有动作,数据会被清走
注意的是,gc不是每次启动会话都会被执行,而是由session.gc_probability 和 session.gc_divisor的比率决定的
结论:控制SESSION的生存期有几种方法
一是cookie_lifttime,这种方式无论有无动作,都会在指定时间内销毁
二是在read中根椐保存时间控制,此方法在有动作时时间会一直有效
三设定session.gc_probability 和 session.gc_divisor的比率为1(即每次会话都会启用gc),再设定gc.maxlifetime来指定生存期,此方法也是在用户有动作时时间一直有效
3)回调函数的执行时机
open 在运行session_start()时执行
read 在运行session_start()时执行,因为在session_start时,会去read当前session数据并写入$_SESSION变量
destroy 在运行session_destroy()时执行
close 在脚本执行完成或调用session_write_close() 或 session_destroy()时被执行,即在所有session操作完成后被执行
gc 执行概率由session.gc_probability 和 session.gc_divisor的值决定,时机是在open,read之后,即session_start会相继执行open,read和gc
write 此方法在脚本结束和使用session_write_close()强制提交SESSION数据时执行
结论:
session_start //执行open(启动会话),read(读取session数据至$_SESSION),gc(清理垃圾)
脚本中间所有对$_SESSION的操作均不会调用这些回调函数
session_destroy //执行destroy,销毁当前session(一般是删除相应的记录或文件),相应地,此回调函数销毁的只是session的数据,但此时
var_dump一下$_SESSION变量,仍然有值的,但此值不会在close后被write回去
session_write_close() //执行write和close,保存$_SESSION至存储,如不手工使用此方法,则会在脚本结束时被自动执行
清晰了以上信息,将对你清楚了解SESSION的工作原理有很大的帮助...
4)直接使用memcache作session处理
在我写了一系列的memcache来保存session的代码后,无意中发现,可以直接在php.ini中设定使用memcache作为session处理,而无须另外编码,方法是:
修改php.ini中的以下值
session.save_handler = memcache
session.save_path = \'tcp://host1:11211\' #有多个时直接用","分隔即可
如果只想在特定的应用里使用memcache储存session,可以使用ini_set的方法对以上两个参数进行设定
要测试一下是否真正用上了memcache,可以先捕足到使用的PHPSESSID,再作为KEY用memcach去读一下,就清楚了