Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/248.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP、MySQL、Cron高效维护大型表中当前/实时数据的方法?_Php_Mysql_Sql Server_Database_Cron - Fatal编程技术网

PHP、MySQL、Cron高效维护大型表中当前/实时数据的方法?

PHP、MySQL、Cron高效维护大型表中当前/实时数据的方法?,php,mysql,sql-server,database,cron,Php,Mysql,Sql Server,Database,Cron,这主要是理论上的,所以如果它变得冗长,我道歉 背景 我正在从事的项目从其他网站(外部网站,而不是由我们托管)获取信息。我们希望获得尽可能接近实时的信息,以便向我们的用户提供即时相关的信息。这意味着要不断监视和更新表 很难展示我以前在这方面的工作,但在过去的几周里,我到处寻找“在数据库中维护实时数据”和“在发生外部更改时立即更新数据库”等类似内容。但一切都无济于事。我认为维护最新记录的问题很常见,所以我不确定为什么彻底解决这个问题似乎如此罕见 为了遵守SO的指导原则,我不是在征求意见,而是在寻找当

这主要是理论上的,所以如果它变得冗长,我道歉

背景

我正在从事的项目从其他网站(外部网站,而不是由我们托管)获取信息。我们希望获得尽可能接近实时的信息,以便向我们的用户提供即时相关的信息。这意味着要不断监视和更新表

很难展示我以前在这方面的工作,但在过去的几周里,我到处寻找“在数据库中维护实时数据”和“在发生外部更改时立即更新数据库”等类似内容。但一切都无济于事。我认为维护最新记录的问题很常见,所以我不确定为什么彻底解决这个问题似乎如此罕见

为了遵守SO的指导原则,我不是在征求意见,而是在寻找当前的最佳实践和业界最常用/公认的有效方法。

目前,使用
cron作业
,我们能做的最好的事情就是每分钟运行一个进程

* * * * * cd /home/.../public_html/.../ && /usr/bin/php .../robot.php >/dev/null 2>&1
问题是,我们正在从数千个其他站点(每行都是一个站点)提取数据,有时更新可能需要几分钟或更长时间。一分钟只调用一次函数是不够的。理想情况下,我们需要近乎即时的解决方案

检查行是否需要更新很快。基本上只是简单的哈希比较:

if(hash(current) != hash(previous)){
    ... update row ...
}
使用cron作业以独占方式触发的进程意味着,如果某一行最终得到更新,则该进程将被挂起,直到完成为止,或者直到cron作业在一分钟后触发新进程为止

不,布埃诺!拜!如果由于某种可怕的命运扭曲,每一行都需要更新,那么所有记录都可能需要数小时(或更长时间)才能更新。在那个时候,已经传递的行将过时

注意:数据库的设置方式使当前正在更新的行对新进程不可访问。该函数实质上是沿着表向下爬行,查找下一个尚未读取/更新的可用行,然后潜入。完成更新后,它将继续下一行

当每个进程到达表的末尾时,或者当表中的所有行都标记为已读时,就会终止该进程。此时,所有行都被重置为未读,流程重新开始

由于收集了大量数据,提高分辨率的唯一方法是同时运行多个进程

但是有多少是太多了

可能的解决方案(方法)

到目前为止,我提出的最好的方法是,尽快通过所有行,如下所示:

  • Cron作业调用第一个进程(P1)

  • P1浏览表,直到找到一行未读且需要更新,然后潜入

  • P1一进入该行,就调用第二个相同的进程(P2)从该点继续

  • P2浏览表,直到找到未读且需要更新的行,然后潜入

  • P2一进入该行,就调用第三个相同的进程(P3)从该点继续

  • 。。。等等

    本质上,每次流程输入一行进行更新时,都会调用一个新流程继续

    但是。。。父进程不是死的。这意味着一旦完成更新,他们就开始再次对表进行爬网,寻找下一个可用行

    而且。。。最重要的是,新的cron作业仍然每分钟都会被触发

    这意味着可能有数千个相同的进程同时运行。进程数不能超过表中的记录数。最坏的情况是,每一行都同时更新,并且在任何更新完成之前触发一两个cron作业。cron作业将立即停止,因为没有行可更新。当每个进程完成更新时,它也会因为同样的原因立即死亡

    上述情况是最坏的情况。每次传递不太可能需要更新超过5或10行,但理论上可以同时更新每一行

    可能的改进(主要在资源上,而不是速度或分辨率上)

  • 监视并限制允许的活动进程的数量,并杀死任何已启动的新进程。但这就引出了一些问题,比如“多少是太多了?”,以及“达到某个分辨率所需的最小数量是多少?”

  • 让每个进程一次标记多行(5-10),直到集合中的所有行都处理完毕后再继续。这将使并发进程的最大数量减少一倍,即每次标记多少行

  • 正如我在开始时所说的,对于数据库架构师来说,这无疑是一个常见的问题。对于维护当前记录,是否有比我所列出的更好/更快/更有效的方法


    谢谢你陪我

    首先,我读了所有内容!我不得不为此拍拍自己的背:)

    您可能正在寻找的是工作队列。排队基本上就像你在超市里看到的那样,一个工作人员就是柜台上的女人,她接受钱,为每个顾客做一切。没有顾客时,她不工作,有顾客时,她工作

    当商场里有很多顾客时,更多的工人会去空柜台,购买食品杂货的人会被分配给所有人

    最近我写了很多关于队列的文章,我最推荐的是Beanstalk。它使用起来很简单,并且使用了PheanstalkA
    <?php
    $pheanstalk = new Pheanstalk('127.0.0.1:11300');
    $pheanstalk
      ->useTube("my_queue")
      ->put("UPDATE mytable SET price = price + 4 WHERE stock = GOOG");//sql query for instance
    ?>
    
    <?php
        $pheanstalk = new Pheanstalk('127.0.0.1:11300');
    
        if ($job = $pheanstalk
        ->watch('my_queue')
        ->ignore('default')
        ->reserve())//retreives the job if there is one in the queue
        {
            echo $job->getData();//instead of echoing you would 
                                 //have your query execute at this point
    
            $pheanstalk->delete($job);//deletes the job from the queue
        }
    }
    ?>