PHP连续检查数据库中的更改的最佳做法是什么?

时间:2012-12-07 06:58:16

标签: php cron

我正在构建一个后端模块(用PHP编写),用于监控私人聊天室,这些聊天室没有[完全] 300秒(5分钟)的活动。如果是,脚本将更新数据库(将最大用户设置为特定数量和其他内容)。我通过now()和最后一条消息的时差监视空闲时间的跨度。


我做了什么:设置一个cron作业,每分钟或60秒运行(通过php-cli)我的监控脚本。在监控脚本中:

$expire_time = time() + 60;

//this loop will run for 60 seconds
while(time() < $expire_time)
{
  $idle_time = get_all_chatrooms_idle_time();
  foreach($idle_time as $s_time)
  {
    if($s_time >= 300)
    {
      update_changes();
    }
  }
  usleep(500000);
}

在300秒空闲时间后立即设置最​​大用户的条件无法进行讨价还价。所以我真的不能遵循这样的建议:“避免做任何事情直到事情要求它”,即使它很有意义。

原因?活动和非活动聊天室的数据需要是实时的,因为它也将显示在仪表板上。聊天室主持人的薪水取决于它。


为什么不检查每个仪表板负载?对不起,但仍然不可能。

检查需要是服务器端,仪表板用ajax更新自己,每秒轮询一次。

当我将监控代码附加到我的ajax调用请求的页面时,我认为它比我当前的实现更耗费资源(如果我错了,请纠正我)

让我粗略估计用户数量,以便您可以想象我们获得的负载/流量:

  • 聊天者的数量,包括主持人:~800
  • 聊天室数量:~250
  • (x)聊天室版主的数量:~50
  • (x)我的老板和他的员工:

(x) - 可以查看仪表板


有更好的方法吗?我做得对吗?

3 个答案:

答案 0 :(得分:2)

这个循环太过分了。即使在中等服务器上,它也可能每分钟运行数千次,即使对于实时应用程序也会产生高CPU使用率。添加计数器,并查看迭代计数。我认为这会产生比处理每个AJAX请求更多的负载。

首先,确定您需要信息的粒度。假设您选择了3秒的粒度(例如每3秒扫描一次数据库) - 这个数字可能对您来说太高了,但它表明您不会损失太多。随着AJAX每秒钟拉动你 COULD 看到一些应该爬行的计数器不断爬回一次或两次。 (你是否真的会看到这样的东西取决于你的柜台的性质。)

如果您的计数器基于秒数范围内的数据(例如显示经过的秒数或基于$ /秒的数量),则第二次AJAX拉动将不提供连续计数器。 (由于网络原因,它有时会错过第二次或更新到第二次;

无论选择何种粒度,您的最终统计数据都是正确的,因为它们基于绝对时间戳 - 无论评估的时间有多晚。

如果使用二次AJAX轮询来实现平滑计数器,那么你可以做得更好:计数应该在客户端运行(例如,以第二个增量发送值:revenue: <span data-inc="25">14432</span>并计数与JS)。唯一实现AJAX监视停止/重置计数器的条件。然后,您只需确定通知可能延迟多长时间(例如10秒),然后计数器将覆盖最大值。 10s回落到预期值。在这种情况下,您不应该更频繁地运行数据库清理(例如,间隔的一半)。这允许例如在你的周期中进行3秒的睡眠,这会大大减少负荷。

如果您可以轻松选择将每个聊天室的过期时间戳添加到数据库(记录中或固定),其索引可以加快读取速度(并且还允许每个房间的过期规则)。 / p>

答案 1 :(得分:1)

根据评论,我建议使用node.js等技术,这是一个偶数驱动的I / O异步平台,用于构建应用程序。如果聊天室是外部应用程序,您可以轻松打开一个套接字并收听聊天室,记录它,检查用户的活动,并监听特定事件。

答案 2 :(得分:1)

#!/usr/bin/php
<?php

if( file_exists('/tmp/chatrooms_cron.lock') ) {
   die( 'There is already a script running.' );
}

file_put_contents( '/tmp/chatrooms_cron.lock', 1 ); // Storing pid would be better 

// Run loop forever
while( true )
{
  $idle_time = get_all_chatrooms_idle_time();

  foreach($idle_time as $s_time)
  {
    if($s_time >= 300)
    {
      update_changes();
    }
  }

  sleep( 60 );
}

提示node.js(使用socket.io):

我一直在使用node.js工作!将是实时的,并使用浏览器低至ie5 / ie6。这可以在node.js内部完成。

setInterval( function() {
   // Fetch and update peers
}, 300000 );