之前没有怎么接触过session,而接手的项目中,由于session,遇到了一些问题:php使用NFS目录存储session PHP的session与ajax的性能冲突 。虽然通过将session的save_handler改为memcache,而消除了性能的问题,但是为了了解为什么,看了下php的session的ext代码,以补充我对session的了解不足。

首先了解下php.ini中对于session的配置:

session.save_handler = memcache
session.save_path = “tcp://192.168.80.27:11211″
;session.save_handler = files
;session.save_path = “/tmp/stry/php_session”
session.use_cookies = 1
session.cookie_secure = 0
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly = 1
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor     = 100
session.gc_maxlifetime = 1440
session.bug_compat_42 = 1
session.bug_compat_warn = 1
session.referer_check =
session.entropy_length = 0
session.entropy_file =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.hash_function = 0
session.hash_bits_per_character = 4

这里我主要关注了save_handler,默认的是file,在多服务器环境常用到数据库、memcache等。

php的session代码位于php-src/ext/session,主要代码中session.c文件中。从session_start函数看起:

php-session-start函数流程图

php-session-start函数流程图

可以看到,其实session的存储,都是交给handler处理的,默认的file handler在mod_files.c中。一个标准的handler会含有以下黑体函数:

#define PS_MOD(x) \

#x, ps_open_##x, ps_close_##x, ps_read_##x, ps_write_##x, \

ps_delete_##x, ps_gc_##x, php_session_create_id

查看mod_file.c可以看到,PS_OPEN_FUNC(files)中,仅将存储的文件名等准备好,并不真的打开,而PS_READ_FUNC中,才真正调用ps_files_open函数打开文件并加锁:

data->fd = VCWD_OPEN_MODE(buf, O_CREAT | O_RDWR | O_BINARY, data->filemode);

flock(data->fd, LOCK_EX); #Place  an  exclusive  lock.  Only one process may hold an exclusive lock for a given file at a given time.

这里可以看到使用了互斥锁!!该锁在文件关闭的时候释放,对于file handler来说,也就是在显示调用session_write_close或者本次请求结束的时候。所以,如果没有调用session_write_close,就会造成对同一请求的session,在使用file handler的时候,是串行的!从而减慢了访问的速度!

memcache的session handler在memcache-src/memcache_session.c中,大致看了下,没有与lock相关的操作,所以,并不是memcache的读写速度远超过file,而是由于它没有ex锁,才造成将handler换成memcache后,大大提高了访问速度!

Leave a Reply