使用 $_SESSION 缓冲/缓存 MySQL 查询
Posted
技术标签:
【中文标题】使用 $_SESSION 缓冲/缓存 MySQL 查询【英文标题】:Using $_SESSION to buffer/cache MySQL queries 【发布时间】:2012-04-28 20:53:53 【问题描述】:我正在开发一个网站。目前,我正在使用cheapo 共享主机。但是男孩可以做梦,我已经在考虑我网站上的大量用户会发生什么。
访问者需要偶尔写入数据库,因为他们在网站上的游戏进度会被记录。
我想通过将进度和其他信息实时写入$_SESSION
变量来最小化查询。并且只有在会话被销毁(注销、浏览器关闭或超时)时,我才想将$_SESSION
的内容写入数据库。
问题:
这可能吗?当会话因超时或关闭浏览器而被破坏时,有没有办法执行函数?
这有意义吗?对于共享服务器来说,几百个并发 SQL 查询是否会成为问题?使用$_SESSION
作为缓冲区的想法可以缓解其中的一些问题。
【问题讨论】:
【参考方案1】:有没有办法在会话被销毁时执行函数 浏览器超时或关闭?
是的,但它可能不像你想象的那样工作。您可以使用session_set_save_handler
定义您自己的自定义会话处理程序,部分定义是提供destroy
和gc
回调函数。这两个在会话被显式销毁以及由于过期而被销毁时调用,因此它们完全按照您的要求执行。
但是,由于超时而导致的会话到期不会以发条精度发生;过期会话实际上“垃圾收集”可能需要很长时间。此外,垃圾回收会触发probabilistically,因此在理论上有可能过期的会话永远不会被垃圾回收。
这有意义吗?有几百个并发 SQL 查询在进行吗 成为共享服务器的问题,并且是使用 $_SESSION 的想法 作为缓冲来缓解其中的一些问题。
我真的不会这样做有几个原因:
过早的优化(在测量之前,不要只是假设它会“更好”)。 会话可能永远不会被垃圾收集;即使这没有发生,您也无法控制何时它们被收集。这可能是个问题。 可能会丢失会话包含的所有内容(例如服务器重新启动),其中包括玩家进度。玩家不喜欢失去进度。 同一用户的并发会话是不可能的(谁的“已保存数据”获胜并保留在数据库中?)。替代品呢?
好吧,既然我们谈论的是 el Cheapo 共享主机,你肯定不会控制服务器,所以任何涉及 php 扩展(例如 memcached)的东西都是有条件的。数据库端缓存也不会飞。此外,您的服务器上的负载会受到您无法控制的变量的影响,因此您无法真正进行任何容量规划。
在任何情况下,我都会首先确保数据库本身的结构是最佳的,并且代码的编写方式可以最大限度地减少数据库的负载(只需在编辑器中输入内容即可释放性能)。
之后,您可以引入只读缓存:通常有很多东西需要显示但不打算修改。对于“几乎永远不会”更新的数据,您可以在需要时使会话缓存失效,这可能是一个简单且非常有效的改进(您甚至可以在失效方面出现误报,只要它们在宏伟的计划)。
最后,如果您担心在单个请求中两次从数据库中提取相同的数据,您可以添加每个请求的缓存(在变量中)。
【讨论】:
酷,不知道。我一直在寻找类似的东西:) 谢谢!【参考方案2】:在会话被销毁时写入数据不是一个好主意。由于会话数据可以通过您的主机配置的垃圾收集器销毁,因此您不知道会话何时真正关闭,直到用户的 cookie 过期。
所以...我建议您使用共享内存 (RAM) 缓存系统,如 memcache(如果您的主机提供)或基于磁盘的缓存系统。
顺便说一句,如果您的查询经过优化、列正确编入索引等,您的共享主机可能会“同时”处理大量查询。
【讨论】:
memcache 绝对是要走的路,它比会话存储/写入更能减轻乐福鞋的重量。 在知道自己有问题之前不要优化。当您有足够的负载时,这是一个问题,您的主机无论如何都会让您移动到自己的专用服务器。【参考方案3】:这有意义吗?对于共享服务器来说,几百个并发 SQL 查询是否会成为问题?使用 $_SESSION 作为缓冲区的想法是否可以缓解其中的一些问题。
没有。首先,您永远不知道会话会发生什么(注销很明显,超时几乎无法检测到),因此无论如何它都不是值得信赖的缓存机制。如果您在几个请求的范围内多次查询结果,但这些结果不会经常更改,请将这些查询的结果保存到专用缓存机制,例如 APC 或 memcached。
现在,我知道您的虚拟主机不会提供这些缓存系统,但是,您可能可以做不同的事情来优化您的网站。对于初学者来说,我最复杂的软件产品(非常相当复杂)平均每页查询数据库大约 6 次。如果结果是可重用的,我倾向于使用缓存,这样可以减少查询次数。
除此之外,编写体面的查询更为重要;您的设计和查询的质量比数量更重要。如果你的架构、索引和查询正确,10 个查询比一个未优化的查询要快。我会花时间研究如何编写高效的查询并阅读索引,而不是尝试通过“解决方法”来解决问题,例如在会话中缓存。
祝你好运,我希望你的网站取得如此巨大的成功,你实际上需要上面的建议;)
【讨论】:
【参考方案4】:实际上,您可以使用 $_SESSION 作为缓冲区来避免重复读取,这对我来说似乎是个好主意(memcached 甚至比这更好),当然不是为了延迟写入(这要复杂得多,应该由分贝);
您可以使用保存在 $_SESSION 中的简单哈希
$cache = array();
$_SESSION['cache'] = $cache;
那么当你必须进行查询时
if(isset($_SESSION['cache'][$id])
//you have a cache it
$question = $_SESSION['cache'][$id];
else
//no cache, retrieve your $question and save it in the cache
$_SESSION['cache'][$id] = $question ;
【讨论】:
以上是关于使用 $_SESSION 缓冲/缓存 MySQL 查询的主要内容,如果未能解决你的问题,请参考以下文章