2011-11-26 79 views
4

通常,我会通过在php中对每个页面加载执行查询来保存所有用户活动,页面视图和所有值。在会话结束时将所有用户活动存储为会话值并保存会话值

  • 现在我想保存所有这些为会话值和 在会议结束执行查询。但是,我不知道如何在PHP中处理这个“结束会话”事件。

我想过在会话超时之前存储所有会话值的后台进程,但我对php中的多线程方法一无所知,尽管我听说过一些规避是可能的。

  • 我想确定用户是不活动的,而不需要用户 触发(如页面加载),并保存所有的会话值在会话的 结束,超时之前。

这将节省一些工作量上的数据库引擎,在这样的方式: 用户意见多页,我增加值闭会期间,执行像

update pageviews set numberofviews=numberofviews+1 

上查询的insetead每页加载。

  • 问题是这样的:“我该如何处理在PHP 会话事件的结束而无需用户活动?”

解决方案的实际问题也赞赏。不管与粗体问题的相关性如何。 (我还没有开始写这个代码,我的问题是不是bug修复。)

可能的解决方案:

我已经找到了php session handler functioon但文件并没有说明它是否能有回调的参数的空参数什么?

如果为$回调参数输入空参数,是否会失去标准功能?

我只想更改会话$ destroy事件。我现在需要帮助。

相关帖子: RP1

+0

这个问题与多线程有什么关系。 – robert

+0

apc,memcache,redis的工具都不符合你的要求? – ajreal

回答

0

有点偏离了轨道,但你可以做你自己的垃圾回收。

  • 使用PHP将会话保存在目录中,最好是tmpfs,禁用垃圾回收功能。

  • 写一个周期性的PHP脚本查找所有会议文件,20多分钟的时候,打开它们,它们写入数据库,并删除它们。

+0

在我看来,这是正确的答案。在你的情况下,会话不会被脚本销毁(=用户操作),但是当它已经足够大以便清理。当任何* PHP脚本运行时,这种垃圾收集通常会有一定的机会完成。将你的会话放到一个单独的目录中,以防止它们被“外来”清理并禁用默认的垃圾收集。然后创建自己的收集器,在清理会话之前存储内容。如果你想让它由用户运行的PHP脚本独立出来,那么你需要一个cronjob。 – BurninLeo

3

你真的不能使用session_destroy处理程序,因为它只是调用,如果你显式调用session_destroy,如果用户只是关闭浏览器并结束会话,这将不会发生。由于在这种情况下无法捕获会话结束“事件”,因此您必须改为进行某种类型的定期检查,以查看会话是否在给定的时间段内处于空闲状态。最简单的方法是在会话中创建一个包含最后访问时间的字段,然后定期创建一个脚本(通过cron或触发PHP脚本中的其他功能),检查该字段是否存在所有活动会话,对于时间戳超过xx秒的任何时间戳,请运行更新查询。

注意,为了做到这一点使用其存储,你必须真正打开文件并直接解析到文件系统上的标准的PHP会议。另一种方法是将会话存储在数据库中,但这可能不是你想要做的事情,因为你试图减少db的负载。

另外一个可能性,这是不太开发密集是:

  1. 添加最后访问的时间戳到您的会话
  2. 检查,每次时间戳您更新会话
  3. 如果时间戳记早于xx秒在数据库上运行更新查询并将时间戳设置为当前时间。

这样你只更新数据库,而不是每次页面加载。这种方法的缺点当然是,除非会话中的最后一个活动与调用更新功能的时间间隔完全一致,否则您可能不会将最新的会话信息存储在数据库中。

1

只是胡乱想到这里,你可以触发一个HTTP请求从javascript节省窗口卸载您的会话数据。问题是浏览器通常会在页面关闭后停止请求,因此这个请求可能不会触及服务器,但我想这是值得进行测试的。

1

虽然有一些变通方法,每一个你能找到解决这个问题的解决方案会比在每个请求记录每个用户活动更加低效。

1

你想解决什么问题?我不明白你为什么不会为启动一个更新查询到数据库的每个请求。它不应该花费比0.0001更长的时间。

我都肯定会去更新每个请求。它是1行代码,不会对数据库造成任何过度负载,并且效率更高。

你提出的方法是很难测试,造成不必要的负担,甚至可能会造成全球性的状态。您可以通过仅使用传统解决方案来防止所有这些。会议是确定何时“结束”的(...)。

+0

在asp.net –

+0

Update =写入操作中很容易。硬盘驱动器有70-150个iops,当负载增加时,你开始注意到这一点。 – c2h5oh

+0

有大量的查询需要执行每个请求,这一个不会是最重的。 – Sherlock

2

这不是创建会话的原因,所以您尝试实现的目标不仅仅是会话机制。

随着标准的PHP会话您的选择是比较有限的,并取决于会话存储:

  1. 默认会话存储在文件中。如果禁用会话垃圾回收,则可以运行一个cron作业,该作业将解析比您定义的时间早的会话文件。这并不完美,但是迄今为止最简单。此外文件会话吸 - 写每个请求。
  2. 会议在Memcached。由于没有好的方法来获取比x更早的记录,并且Memcached只会在数据过期时丢失数据,这一点在这里可以做的不多。
  3. DB中的会话 - 您已经更新了每个请求。

因此,您在标准会话中的选择最多是有限的。我的建议是:用您自己的标准会话替换标准会话,但这意味着您将不再通过$ _SESSION访问会话,并需要您重写很多代码。

我用一个存储会话数据在APC/Memcached以及数据库中的单例替换了常规会话。会话数据仅在我请求时保存在数据库中(Session::persistentStore($key,$value)),或者在处理请求期间,APC/Memcached存储的会话数据表明它没有写足够长的时间。这限制了很多写入次数。 有了这个替代品,您只需强制从数据库端保存会话:从数据库中获取尚未更新x分钟的会话的会话ID,从APC/Memcached为每个数据提取信息,并且如果没有更新信息那里(指示会话将很快结束)保存到数据库。

1

我想到了刚刚在会话超时之前存储所有会话值 一个后台进程,但我不知道在PHP 多线程方法什么,即使我已经听到了一些 规避被可能。

如果你很容易地使用基于db的会话,你可以这样做。

  1. 不需要多线程
  2. 写运行,每分钟/5分钟
    • cron作业选择的所有记录即将到期
    • 将它们保存到其它表

关键是使用cron作业,而不是尝试处理http请求中游的到期事件

+0

太贵了 –

1

你在谈论延迟统计写入和会话管理。我猜,你真正的问题是要避免在数据库上写per-http-requests写查询。

一些提示,可能对于这样的问题是有用的:

  1. 小心在会议并行访问。我们通常认为会话只能通过一个进程来访问,但这是错误的,比方说,例如,您正在执行多文件上传,一些js向服务器打开多个ajax请求,每个进程都使用同一个会话。使用浏览器在同一网站上打开10个选项卡时也是如此。
  2. 添加更新查询对于每个请求是一个重的东西。选择查询很快,通常在SQL端使用某种缓存。更新查询很慢,可能是重建索引,并且通常意味着SQL Server上的某些缓存清理操作。如果您在数据库上使用不同的用户进行只读或读写访问,则它们也可能意味着不同的SQL会话。
  3. 会话大小不宜过大,因为会议必须装载每个请求,并且每次东西在你的会话(因为1)锁定机构设置和数据被推送到实体会话存储(默认文件)。所以会话写入会减慢你的过程。
  4. 一个NoSQL的后端,如MongoDB的reddit的可能是保存每个请求的统计数据的好地方,他们有正确的工具来确保原子更新,锁和可能真的比Relationnal数据库更快地执行(但你也可以在关系数据库中检查内存表的性能)。因此,您可以使用这些工具来跟踪活动并通过将这些后端用作实时统计的主要目标来避免SQL更新。你可以异步从你的数据库的后端收集一些statictics。现在会话是临时对象,这些NoSQl后端也可能是好的会话存储(如果您编写自己的会话存储处理程序)。

编辑:与并行使用原子更新问题例如:执行查询要求的增量计数器=计数器1是一样读计数器,递增它并执行更新查询计数器= mynewvalue。当多个进程使用相同的数据时,第二个错误是错误的。