在没有浏览器超时的情况下在PHP中处理大量数据

时间:2011-04-03 22:53:27

标签: php mysql codeigniter codeigniter-2

我有大约50,000个手机号码。我正在尝试使用第三方API处理并向这些号码发送批量短信,但浏览器会冻结几分钟。我正在寻找更好的选择。

数据处理涉及检查手机号码类型(例如CDMA),为所有号码分配唯一ID以便进一步参考,检查网络/国家/地区的独特费用等。

我想过将数据排队到数据库中并使用cron每分钟批量发送大约5k,但如果有很多消息需要时间。我有什么其他选择?

我在XAMPP服务器上使用Codeigniter 2.

4 个答案:

答案 0 :(得分:37)

我会写两个脚本:

档案index.php

<iframe src="job.php" frameborder="0" scrolling="no" width="1" height="1"></iframe>
<script type="text/javascript">
    function progress(percent){
        document.getElementById('done').innerHTML=percent+'%';
    }
</script><div id="done">0%</div>

档案job.php

set_time_limit(0);                   // ignore php timeout
ignore_user_abort(true);             // keep on going even if user pulls the plug*
while(ob_get_level())ob_end_clean(); // remove output buffers
ob_implicit_flush(true);             // output stuff directly
// * This absolutely depends on whether you want the user to stop the process
//   or not. For example: You might create a stop button in index.php like so:
//     <a href="javascript:window.frames[0].location='';">Stop!</a>
//     <a href="javascript:window.frames[0].location='job.php';">Start</a>
// But of course, you will need that line of code commented out for this feature to work.

function progress($percent){
    echo '<script type="text/javascript">parent.progress('.$percent.');</script>';
}

$total=count($mobiles);
echo '<!DOCTYPE html><html><head></head><body>'; // webkit hotfix
foreach($mobiles as $i=>$mobile){
    // send sms
    progress($i/$total*100);
}
progress(100);
echo '</body></html>'; // webkit hotfix

答案 1 :(得分:1)

我假设这些数字在数据库中,如果是这样,你应该添加一个名为isSent的新列(或任何你想要的)。

您键入的下一段应该排队,并且可能在适当的时候每晚/每周进行一次。除非您有特殊原因,否则不应按需批量进行。您甚至可以向数据库添加一列以查看上次检查的时间,以便在至少X天内未检查到某个数字时,您可以根据需要检查该数字。

  

数据处理涉及检查手机号码类型(例如CDMA),为所有号码分配唯一ID以便进一步参考,检查网络/国家/地区的独特费用等。

但是这仍然会让你回到同样的问题,即如何同时为50,000个号码做这件事。既然你提到了cron作业,我假设你有SSH访问你的服务器,这意味着你不需要浏览器。这些cron作业可以通过命令行执行:

/ usr / bin / php /home/username/example.com/myscript.php

我的建议是每10分钟通过cron一次处理1,000个号码,并计算这需要多长时间,然后将其保存到数据库中。由于您使用的是cron作业,因此它们似乎不是时间敏感的SMS消息,因此它们可以展开。一旦你知道这个脚本运行50次(50 * 1000 = 50k)需要多长时间,那么你可以更新你的cron作业以更频繁地运行。

$time_start = microtime(true);
set_time_limit(0);

function doSendSMS($phoneNum, $msg, $blah);

$time_end = microtime(true);
$time = $time_end - $time_start;
saveTimeRequiredToSendMessagesInDB($time);

另外,您可能已经注意到了set_time_limit(0),这将告诉PHP在默认的30秒后没有超时。如果您能够修改PHP.ini文件,则无需输入此行代码。即使您能够编辑PHP.ini文件,我仍然建议您不要更改此功能,因为您可能希望其他页面超时。

http://php.net/manual/en/function.set-time-limit.php

答案 2 :(得分:1)

如果这不是一次性的情况,请考虑设计更好的解决方案。

您基本上想要的是您的浏览器绑定进程可以写入的队列,而不是1-N工作进程可以读取和更新的队列。

将工作放在队列中应该相当便宜 - 可能是SQL RDBMS的一堆简单的INSERT语句。

然后你可以有一个或两个(或100个,分布在多个服务器上)的守护进程从队列中读取和处理东西。你在这里要小心,避免两个工作人员承担相同的任务,但这并不难编写代码。

因此,您的浏览器绑定工作流程是:单击某个按钮,将一堆内容添加到队列中,然后重定向到某个“队列状态”界面,用户可以在其中查看系统咀嚼所有工作。

像这样的系统很不错,因为它很容易横向扩展。

编辑:Christian Sciberras的回答正朝着这个方向发展,除了浏览器最终驱动双方(它增加了队列,然后驱动工作进程)

答案 3 :(得分:0)

Cronjob将是您最好的选择,我不明白为什么在浏览器中执行此操作只需要浏览器超时的唯一问题。

如果您坚持通过浏览器进行操作,那么另一个解决方案就是分批执行1000次并重定向到相同的脚本,但需要参考上次在$ _GET变量中的位置。< / p>