现在稍微大一点的网站基本上都有好几个子域名,比如,,这些网站如果需要共享用户的登录信息,就必须session共享。PHP又是如何做到多个服务器,session共享的呢?
要解决这个问题我们首先要明白session的工作原理是什么?
session原理
客户端访问PHP服务器时,执行session_start生成session_id,一般我们会把session_id存储到cookie中,根据session_id关联内容并保存在服务器文件系统中,每一次请求通过cookie获取session_id,再通过session_id获取session内容。
但是客户端访问不同服务器时,每一台服务器都会生成一个session_id,这就导致不同服务器之前无法共享session了。
解决session共享其时就两个步骤
多台服务器对于同一个客户端生成同一个session_id
这个比较好解决,只要我们针对主域名来生成session_id即可。实现的方式有两种:
1.1 通过php配置文件设置session_id的cookie域名。找到php.ini文件添加如下配置:
session.cooke_domain = .
1.2 通过代码设置session_id的cookie域名,代码如下:
ini_set( 'session.cookie_domain' , '' );
多台服务器之前的session内容互通有无,可以通过同一个session_id获取到内容
这一点实现起来比较麻烦,主要就是把session存储在所有服务器都可以访问的地方。默认的存储在服务器的文件中,我们也可以存储在 Redis 这类缓存服务器中。对于文件系统我们可以通过 NFS 来统一存储。
2.1 文件系统
这种方式的session依赖于PHP垃圾收集器进行销毁,在高并发下session存储的目录下会产生大量的文件。这种方式会导致查找文件缓慢,并且session缓存目录可存储的文件数是有限的,有可能导致session存储失败,因此,我们不建议使用文件系统存储session。
2.2 数据库存储
这种方式虽然不依赖PHP的垃圾收集器,但是会加大数据库的IO问题,增加数据的压力,导致数据读写速度变慢,因此这种方式,我们也不建议大家使用。
2.3 Redis 缓存存储
缓存数据都在内存中,读写速度快,redis还可以单独设置过期时间,自动删除无效的session。
现有的PHP框架基本都支持Redis存储session,我们只需要配置好session相关配置即可。当然如果你想自己但对编写session相关代码也可以,我给大家一个示例:
<?php//启动sessionsession_start();//设置session最大存活时间,单位【秒】ini_set('session.gc_maxlifetime',60*60);//设置session存储方法ini_set('session.save_handler','redis');//设置session存储路径,存储方式为redis时,路径就是redis的连接(如果不需要授权,直接使用 tpc://127.0.0.1:6379 即可)ini_set('session.save_path','tpc://127.0.0.1:6379?persistent=1&auth=授权密码&database=redis数据库');//设置session内容,在内容中存储当前key的过期时间$_SESSION['user_info'] = ['data'=>['id'=>1],'expire'=>time()+60*30];//获取session内容$data = $_SESSION['user_info'];//判断当前session是否过期if($data['expire']>time()){//删除session中已过期的keyunset($_SESSION['user_info']);echo 'session已过期';}else{print_r($data['data']);}