关于PHP中的会话管理
大致意思
我是TechTrain的工作人员,也是导师的苏。
这次,我整理了一些关于会话管理方面不明白的问题。
首先,会议是什么
会话是指在访问网站并进行一系列操作的过程。
从访问网站开始到离开该网站或关闭浏览器,即为一个会话。
每个Web服务器都有一个唯一的ID,用于跨多个页面的Web系统,
通过使用这个ID来保存和使用每个用户的信息。
在使用这个会话方法中最典型的是通过Web页面进行,而最常用的功能是登录和登出。
将用户从登录到注销的整个过程视为一个会话,并在此期间保存用户ID、密码等状态信息。
在PHP中的默认设置。
将文件保存到服务器。向Cookie中存储的文件分配一个类似于密钥的值(ID),用于查询自己的Session。
除了默认选项外的可行方法(优点和缺点)。
顺便提一下,对于会话的管理方法有几种,但主要的方法如下:
曲奇饼干
以类似于Rails默认情况下的方式,将所有数据保存在客户端的cookie中的方法。
好处
-
- サーバにデータをため込まないので、サーバサイドの負荷を気にしないで良い
- アプリケーションサーバを分散させても一貫性を持たせられる
缺点
-
- ユーザ側にデータがあるため、改ざんリスクが高まる(Railsは暗号化によって対策してますが)
-
- Cookieの仕様上、4KBの容量制限がある
-
- Cookieを乗っ取られた場合等でもサーバサイドからセッションを破棄する手段がない
- ユーザがcookieを有効にしていない場合、ログイン情報などがうまく保存されない
文件
从框架的角度来看,Laravel和CakePHP默认使用Cookie来保存会话ID,并将实际数据作为文件存储在服务器端的方法。
好处
-
- サーバサイドにデータがあるので改ざんを回避できる
-
- データ容量制限がない
- サーバサイドでセッションの破棄ができる
缺点
-
- アプリケーションサーバを分散させた場合、一貫性が確保できない
- 1セッションにつき1ファイル生成されるので、大量にセッションファイルが出来てファイルシステムに負担が掛かる
关系数据库 (RDB)
只需将会话ID保存在Cookie中,并将实际数据存储在MySQL等服务器端的关系数据库中的方法。
优点
-
- サーバサイドにデータがあるので改ざんを回避できる
-
- データ容量制限がない
-
- サーバサイドでセッションの破棄ができる
- アプリケーションサーバを分散させても一貫性を持たせられる
缺点
- RDBは大量の同時I/Oに弱いので、アクセスが増えるとデータベースが一気にパンクする。しかもスケールしづらい。
KVS(非关系型数据库)
只使用Cookie存储会话ID,并将真实数据放在服务器端的KVS,例如Memcached、Redis等的方法。
好处
-
- サーバサイドにデータがあるので改ざんを回避できる
-
- データ容量制限がない
-
- サーバサイドでセッションの破棄ができる
-
- アプリケーションサーバを分散させても一貫性を持たせられる
- 大量の同時I/Oに強く、アクセスが増大しても大丈夫!
劣势
- セッション専用にひとつデータベースが追加されるのでコストが増
内存
一种常见的实施方法是上述技术手段。
饼干
如果想在浏览器关闭后仍然使用这个会话Cookie,请在session_start()之前调用session_set_cookie_params()。
利用这些标准函数,您可以像使用PHP默认的方法处理文件一样将会话保存在cookie中。
session_get_cookie_params 取得会话的cookie参数
session.cookie_lifetime 会话的cookie生存期
session.cookie_path 会话的cookie路径
session.cookie_domain 会话的cookie域名
session.cookie_secure 会话的cookie安全性
session.cookie_httponly 会话的cookie仅限HTTP
文档
这是PHP的默认设置。如果您仅仅使用了标准函数session_start,而没有做任何考虑的话,会话会被保存为一个文件,并存放在session.save_path(默认为/tmp)目录中。
关系型数据库
创建用于会话保存的数据库。
作为一个可能的表格结构,大概是这样子的。
创建一个会话类
创建一个用于将会话信息保存在已创建的数据表中的PHP类。由于将处理任务放在了数据库中,所以或许在MVC中将处理任务放在模型中可能是更好的选择。
在 Session 类中需要的函数有以下六个。
-
- open
-
- close
-
- read
-
- write
-
- destroy
- gc
PHP5.4及以上版本可以通过在会话类中使用SessionHandlerInterface接口轻松实现。此外,在php5.5.1及以上版本中,可以在session_set_save_handler的第七个参数中指定create_sid回调函数。可以利用该函数来发行自定义的会话ID,但要注意避免会话劫持的问题。
設計時的注意事項 shí de
使用InnoDB
这是必须的。不一定是InnoDB,但要支持“行锁”很重要。
-
- 由于插入/更新操作较多,使用MyISAM将导致频繁的数据表锁定。
-
- 上述操作会导致写锁定,因此读操作也会被阻塞。
-
- 由于行锁定,插入、更新和删除操作之间不会发生竞争。
-
- 当然,与查询操作无竞争。
-
- 这对于执行删除操作非常重要。
-
- 在进行mysqldump时不需要锁定表格。
- 从不停止服务的角度来看,这是相当重要的。
只需要一个选择,下面是在中文里的释义:
– 使用–single-transaction选项
为了使用行级锁机制,必须拥有主键或唯一约束的列。
在中国翻译的原生方式是:“设置专用于会话的数据库服务器。” (Set up a dedicated database server for sessions)
如果主数据库中存在会话数据,则可能会对其他数据产生负载影响,因此我们认为最好不对会话进行复制(后面有提及)。
如果主数据库中有会话数据,对其他数据的负载也可能会有影响,因此我们认为最好不进行会话的复制(如后文所述)。
KVS(非关系型数据库)
这可以通过使用PHP中的PHPRedis等工具相对容易地实现。(但是PHPRedis只是其中的一个选择)把PHP会话保存到PhpRedis中是一个简单的实现参考,非常好。谢谢。
内存
如果是PHP5.5或更新的版本,在相应的服务器上安装Apcu;如果是之前的版本,则需要安装apc。这样就可以使用apcu(apc)函数系列进行信息的存储等操作。
当我实际尝试的时候,我使用以下作为简单参考。非常感谢。
将会话保存在内存中。
通常来说
在使用关系数据库(RDB)来管理会话的情况相当普遍。
对于流量较大的网站来说,会话的管理会消耗大量的计算能力。
使用键值存储(NoSQL)可以期望轻松获得显著的效果。
在这方面,最好根据资金和人力成本的平衡来进行修改。
这是我个人的思考或者补充。
利用文件缓存时的文件共享。
提前条件
-
- 使用文件缓存的WEB服务器正在进行多重复制
- 使用GlusterFS将保存的文件缓存目录共享给多个服务器
只要是共享的,无论是不是使用GlusterFS,都可以将其视为同样的条件,对于第3点没有问题。
可能会增加读取负载
当满足以上所述的前提条件时,每个WEB服务器对于一个目录可能会执行过多的读取和写入操作,导致处理部分成为瓶颈,从而使得系统的运行变得缓慢。
除非没有大量的技术债务问题,否则最好尽早采取一些改变,例如使用KVS等机制来进行优化。
其他一些参考
愛家群組-將PHP的會話信息儲存到數據庫(MySQL)中!
慢舞-關於使用數據庫管理會話數據
使用zend-session將會話信息保存到數據庫中
將PHP會話保存到PhpRedis中
APC用戶緩存-PHP官方文檔
更改PHP行為-PHP官方文檔
APC被APCu和Zend OPcache取代的原因