一直以来,由于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去读一下,就清楚了

关于session和memcache的若干问题
标签: