7

我正在开发一个网站。目前,我正在使用cheapo 共享主机。但是一个男孩可以做梦,我已经在考虑我网站上的大量用户会发生什么。

访问者需要偶尔写入数据库,因为他们在网站上的游戏进度会被记录下来。

我想通过将进度和其他信息实时写入$_SESSION变量来最小化查询。只有当会话被破坏(注销、浏览器关闭或超时)时,我才想将内容写入$_SESSION数据库。

问题:

  1. 那可能吗?当会话因超时或关闭浏览器而被破坏时,有没有办法执行函数?

  2. 这有道理吗?对于共享服务器来说,几百个并发 SQL 查询是否会成为问题,并且使用$_SESSION作为缓冲区的想法会缓解其中的一些问题。

4

4 回答 4

6

当会话因超时或关闭浏览器而被破坏时,有没有办法执行函数?

是的,但它可能不像你想象的那样工作。您可以使用 定义自己的自定义会话处理程序session_set_save_handler,并且定义的一部分是提供destroygc回调函数。这两个在会话被显式销毁以及由于过期而被销毁时被调用,因此它们完全按照您的要求执行。

但是,由于超时而导致的会话到期不会以发条精度发生;过期会话实际上是“垃圾收集”可能需要很长时间。此外,垃圾收集是概率性触发的,因此理论上过期会话有可能永远不会被垃圾收集。

这有道理吗?对于共享服务器来说,几百个并发 SQL 查询是否会成为问题,并且使用 $_SESSION 作为缓冲区的想法可以缓解其中的一些问题。

我真的不会这样做有几个原因:

  • 过早的优化(在你测量之前,不要只是假设它会“更好”)。
  • 会话可能永远不会被垃圾收集;即使这没有发生,您也无法控制它们何时被收集。这可能是个问题。
  • 有可能丢失会话包含的所有内容(例如服务器重新启动),其中包括玩家进度。玩家不喜欢失去进度。
  • 同一用户的并发会话是不可能的(谁的“保存的数据”获胜并保留在数据库中?)。

替代品呢?

好吧,既然我们谈论的是便宜的共享主机,你肯定不会控制服务器,所以任何涉及 PHP 扩展(例如 memcached)的东西都是有条件的。数据库端缓存也不会飞。此外,您的服务器上的负载将受到您无法控制的变量的影响,因此您无法真正进行任何容量规划。

在任何情况下,我都会首先确保数据库本身的结构是最佳的,并且代码的编写方式可以最大限度地减少数据库的负载(只需在编辑器中输入内容即可释放性能)。

之后,您可以引入只读缓存:通常有很多东西需要显示但不打算修改。对于“几乎永远不会”更新的数据,您可以在需要时使会话缓存失效,这可能是一个简单且非常有效的改进(您甚至可以在失效方面出现误报,只要它们在宏伟的计划)。

最后,如果您担心在单个请求中两次从数据库中提取相同的数据,您可以添加每个请求的缓存(在变量中)。

于 2012-04-17T13:58:44.680 回答
5

在会话被销毁时写入数据不是一个好主意。由于会话数据可以通过您的主机配置的垃圾收集器销毁,因此您不知道会话何时真正关闭,直到用户的 cookie 过期。

所以...我建议您使用共享内存 (RAM) 缓存系统,如 memcache(如果您的主机提供它)或基于磁盘的缓存系统。

顺便说一句,如果您的查询经过优化,列正确索引等,您的共享主机可能会“同时”处理大量查询。

于 2012-04-17T13:57:59.330 回答
2

这有道理吗?对于共享服务器来说,几百个并发 SQL 查询是否会成为问题,并且使用 $_SESSION 作为缓冲区的想法会缓解其中的一些问题。

不。首先,您永远不知道会话会发生什么(注销很明显,超时几乎无法检测到),因此无论如何它都不是值得信赖的缓存机制。如果您在几个请求的范围内多次查询结果,但这些结果不会经常更改,请将这些查询的结果保存到专用缓存机制,例如APC或 memcached。

现在,我知道您的虚拟主机不会提供这些缓存系统,但是,您可能可以做不同的事情来优化您的网站。对于初学者,我最复杂的软件产品(相当复杂)平均每页查询数据库大约 6 次。如果结果是可重用的,我倾向于使用缓存,这样可以减少查询的数量。

最重要的是,编写体面的查询更为重要;您的设计和查询的质量比数量更重要。如果你的架构、索引和查询正确,10 个查询比一个未优化的查询要快。我会花时间研究如何编写有效的查询并阅读索引,而不是尝试通过“解决方法”来克服问题,例如在会话中缓存。

祝你好运,我希望你的网站取得如此巨大的成功,你实际上需要上面的建议;)

于 2012-04-17T14:04:11.963 回答
1

实际上,您可以使用 $_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 ;
}
于 2012-04-17T14:01:16.270 回答