如何查询,然后在较短的时间内处理大量

戴夫

我有一张大桌子的订单。在设定的时间,我需要向他们的大部分发送一条SMS消息(不幸的是,每个消息的内容不同)(基于他们是否选择了该消息以及是否包含电话号码)。在相当短的时间内,可能有200,000多个数字。(现在还不算高,但是从理论上讲可以并希望如此构建)。

它们并不需要全部立即发送,但是-在设定时间的1-3小时内是理想的选择。

我正在使用带有API的服务来发送它们,所以这不是问题-问题是:

1)如何处理大量

2)如何知道它们都已被处理或重新处理了未处理的那些

认为执行MySQL查询以获取所有200,000多个电话号码然后循环浏览不是一个好主意-我必须假设这会占用大量内存(?)。

所以-我想尝试一项cron作业,并使其每分钟(或大约)运行一次。在该脚本中,我可以提取5,000条记录,标记为“处理中”,然后重复处理每个记录,然后将其行更新为“已发送”。

但这有很多潜在的问题...如果SMS服务变慢而我无法全部发布,该怎么办。如果出现无法预料的错误并且脚本在途中停止运行...等等。如果有任何原因导致该脚本无法发送全部5000条记录,我怎么知道该返回哪些记录并重新处理?

这不仅是此过程,还有其他一些过程-整个问题不断浮出水面,即如何处理需要以某种方式处理的大量行并知道每个行都已完成

我希望我只是把这些废话弄得太复杂了,并且有一些更简单的处理方法。

如果我不清楚,请发表评论,我很乐意进一步解释任何方面。

埃文·德拉克鲁兹(Evan de la Cruz)

简短版本:

  1. 不用担心内存消耗。只是不要尝试立即获取整个结果集。

  2. 使用一个单独的表列出每个文本消息,然后在知道该行是否成功时更新该行的想法通常是正确的方法(是否在cron中执行并不重要)。

  3. 如果您担心SMS提供商可能会丢弃某些请求,则可以使用ActiveMQ或类似的方法实现自己的排队机制但是,这种方式在很大程度上削弱了使用提供程序的目的。他们应该使用自己的队列,以便您不必担心。

细节:

SMS服务应通知您成功或失败。大多数高容量SMS服务将您的消息排队,并一次以n条消息的块发送出去。然后,他们将通过某种回调或Web挂钩通知您,哪些消息成功,哪些消息失败。它们中的大多数还提供API,可让您检查是否已发送某些消息。您需要利用这些功能。

我认为您的Cron方法正处于正确的轨道上。

一种选择是永不“拉”记录。而是在现有表上有一列,以指定是否正在等待消息发送。这样,您无需执行SELECT并处理成千上万的行,而是执行简单的UPDATE,然后当每个回调均来自API时,您可以成功/失败地重新更新行。

如果您可能一次为每一行数据发送多个消息,那么显然这是行不通的。您将必须有一个单独的表,其中每个要跟踪的消息都带有一行。

至于您的内存问题,我认为这不是问题。只是不要获取整个结果集。相反,请分别获取每一行。这将防止mysql返回整个数据集,因此您无需将其保存在内存中。

来自php.net

由于mysqli_fetch_all()在单个步骤中将所有行作为数组返回,因此它可能比某些类似函数(如mysqli_fetch_array())消耗更多的内存,而mysqli_fetch_array()一次仅从结果集中返回一行。此外,如果您需要遍历结果集,则将需要一个循环结构,这将进一步影响性能。由于这些原因,mysqli_fetch_all()仅应在将获取的结果集发送到另一层进行处理的情况下使用。

编辑/修改

解决评论/问题:

我不能每个时间仅提取一个条目-这将是永远的...我知道我也不应该一次获取整个结果集,这就是促使我问“然后我还能怎么做的呢?

在PHP中(将mysqli与mysqlnd结合使用),当您执行查询时,它实际上并不返回数据。它根据您的查询准备要返回的数据,但不会返回。

使用fetch_all时,您要求的是整个结果。当使用fetch_array时,您要求下一个结果,并且告诉mysql移动结果游标,以便可以在那之后获得下一个结果只要您不将每个结果存储在内存中(使用单独的变量),就不会出现内存问题。只需在需要时使用该行,然后获取下一行即可。不管是cron工作,都无关紧要。
您无需一遍又一遍地调用脚本,每行一次。该脚本在一次调用中处理每一行。它只是一次读取一行,以节省内存。

这是一个脚本示例:

$mysqli = new mysqli("host", "user", "pass", "db");
$query = "SELECT * from TextMessages";
$result = $mysqli->query($query);
while ($row = $mysqli->fetch_array($result))
{
    //this is the only thing you store in memory, one single row at a time
    $row = $result->fetch_array(MYSQLI_ASSOC);

    //go send the text message and do whatever else you need to do
    if ($row["SomeSmsToken"] == null && $row["TextHasAlreadyBeenSentOrDateSentOrWhatever"] == false)
    {
        //$someSmsToken = $myTwilioObject->SendByRow($row);
        //$this->UpdateRowToTellItThatItHasBeenSentToProviderAndIsWaitingForResponse($row,$someSmsToken);
        //..etc...
        //then go to the next row.
    }
}
$result->free();

然后,在某些回调脚本中,您将执行以下操作。

$mysqli = new mysqli("host", "user", "pass", "db");
$query = "SELECT * from TextMessages where SomeSmsToken = '".$_POST["SomeTokenSentFromProviderInCallback"]."'";
$result = $mysqli->query($query);
while ($row = $mysqli->fetch_array($result))
{
  $someObject->UpdateRowToSayThatTheTextWasSentOrItFailed($row,$_POST["SomeStatusSentFromProviderInCallback"]);
}

$result->free();

mysqli_free_result完成后,您还可以使用php的mysql驱动程序释放所有消耗的内存。

从php.net:

当不再需要结果对象时,应始终使用mysqli_free_result()释放结果。

编辑:如果您想要某种聪明的方式来处理“如果脚本超时该怎么办”,我建议每分钟运行一次cron。当它运行时,应检查它是否已在运行,如果尚未运行,则应运行它。该脚本将一直有效,直到超时为止。
然后在一分钟之内,cron将再次启动它,由于它没有在运行,因此它将再次运行并在中断的地方继续运行。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在持续时间内处理子向量

如何在较短的时间内查看平均负载?

我们可以使用加特林检查是否在特定时间内处理了请求

如何在较短的时间内使用实体框架同时编辑1000条记录

如何在相对较短的时间内在 OpenCV 中用 python 编辑视频?

在较长的时间内找到较短的几天以进行计算

如何在给定的时间内运行R代码然后停止它?

如何在1个间隔时间内选择数据作为动态查询

再次调用时,JS函数开始在较短的时间内执行

如何在不到1秒的时间内从GAE数据存储中检索大量(> 2000个)实体?

查询一段时间内发生的记录

如何让Windows在最短的时间内说出时间

如何处理用户在一段时间内可以发布的固定最大帖子数?

Impala - 如何查询一段时间内累计销售的产品数量?

如何在设定的时间内递归调用函数?

如何在固定的时间内使用javascript函数?

如何在指定的时间内运行循环

如何在碳日期时间内使用变量?

如何在预定时间内发送报告

如何在更少的时间内重用伪类?

如何在一定时间内循环播放?

如何在更少的时间内定义变量

如何在更少的时间内使用我的vim配置?

蝗虫:如何使蝗虫在特定时间内运行

如何在一定时间内运行代码?

如何在固定时间内返回下标?

如何在窗口ReplaySubject时间内使用TestScheduler

如何在更少的时间内创建动态类

如何在特定时间内锁定Android设备?