PHP SESSION机制原理和CodeIgniter3.0 Session并发冲突问题

 

一、机制原理

Session(英文翻译为“会话”),可以在浏览器和服务器之间建立持续的会话访问。在会话管理期间,Session会在服务器上维护一张登记表,记录(session_id, ip_address, user_agent, timestamp, data)等信息,除了data用于服务器端编程记录信息外,其他都是Session自动维护的。使用Session,依据session id和会话表,在服务器端进行编程,可以实现一次登录身份,短期持续可靠的访问。

1、当用户User登录身份时,通过在浏览器中输入用户名和密码进行登录,服务器编程通过session_start();启用会话,自动调用session_regenerate_id(false);产生并记录下session id和timestamp等信息。这个session id就像一个临时身份证(通常会设置过期时间),通过cookie(COOKIE就是)返回给浏览器,并在浏览器下次访问时自动携带。如果之前带有session id,Session会检查是否过期,如果过期将为访问用户重新生成一个session id,如果没有过期,将更新其它自动维护的信息。

2、当用户User登录身份后,服务器编程可使用Session写入该登录用户的user_id等常用信息,这些信息会被存入data。这样下次用户访问时,可以编程通过$_SESSION[]获取这些信息,获取信息时Session会自动查询会话表。

3、当用户User注销身份时,服务器编程使用session_destroy();终止会话,自动调用session_regenerate_id(true),重新一个session_id,并删除编程保存的data信息。如果用户非正常退出,session会话信息仍然会保存在服务器端,当用户再次访问时,如果身份信息没有过期,将自动登录。如果身份信息已经过期,编程要求用户重新登录。

其它:也可以在登录时,使用session_regenerate_id(true);重新产生一个session id。

二、并发冲突       

在 CodeIgniter 之前的版本中,Session 类并没有实现锁机制,请求是非阻塞的。(requests were non-blocking)。而在CodeIgniter3.0中,Session实现的'files','datebase','memcached'和'redis'驱动中,使用了锁机制,并且在关闭Session时才进行释放。而在通常情况下,程序没有设计主动来关闭SESSION,默认会在php文件执行完毕后关闭Session,进行锁的释放,大大加剧了冲突的程度。所以,在使用session时要解决(准确的说是缓和)冲突,只有在使用完Session后,调用session_destroy();和session_write_close();才会主动关闭Session,缓和并发冲突。

在处理 session 时使用非阻塞的请求同样意味着不安全,因为在一个请求中修改 session 数据(或重新生成 Session ID)会对并发的第二个请求造成影响。这是导致很多问题的根源, 同时也是为什么 CodeIgniter 3.0 对 Session 类完全重写的原因。

主要存在的两种场景:

(1)WEB页面中使用了大量AJAX请求。当网站大量使用了ajax请求时,在多个请求中都使用了session的情况下,由于读取SESSION时会加锁,从而发生冲突。

(2)大量API请求中,启用了Session,并且在APP中保持了COOKIE。公司开发的系统中,使用了nginx分布式部署,为了解决SESSION同步,有采用了数据库持久化的方式。后来,客户反映数据库中的SESSION持久化表数据量太大,系统响应变慢。通过查看log发现:由于访问API的Android终端,支持持久化SESSION的COOKIE数据,造成类似场景(1)中的情景。

 

三、解决办法

1、使用session的情况

如场景一,可以在使用session完毕后,调用session_write_close();关闭会话,释放加锁

2、不使用session的情况

如场景二,只有在API的任何地方都不使用SESSION,才能最彻底地杜绝session并发冲突。(通过研究CI框架Session实现机制发发现,只要SESSION类实例化,就会造成会话数据的写入。)

(1)从application/config/autoload.php中,去除session类和间接加载session类的库类的自动加载。

(2)在使用的任何类库中,都不要加载session类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值