【问题标题】:What is the most efficient way to email a lot of users in PHP?用 PHP 向大量用户发送电子邮件的最有效方法是什么?
【发布时间】:2023-03-16 01:53:01
【问题描述】:

每当有人 PM(私人消息)他们时,我的网站都会向我的用户发送一封电子邮件。它说的是“有人刚刚在站点名称上向您发送了一条消息,请登录以查看它”。

目前我的网站不是很受欢迎,所以我目前的做法在性能方面没有问题:

    // code that sends pm here...

    // code that stores pm in messages table here...

    // notify user by emailing them right away
    mail($user_email, $subject, $message);

基本上,每次发送 PM 时,都会执行邮件功能并在现场发送消息。因此,每发送 100 条消息,mail() 就会被调用 100 次。

我预计我的网站会越来越受欢迎,并且随着用户的增多,PM 也会越来越多,所以我认为我目前的做法将成为性能噩梦。所以我想改用这种方式:

// get the last message that was accounted for by the last cron
$query = mysql_query(" SELECT `last_checked_id` FROM `settings` ");
$last_checked_id = mysql_fetch_array($query);


$user_emails = array();

// get all messages that were added to this table since the last time this cron ran
$query = mysql_query(" SELECT `recipient_id`, `message_id` FROM `messages` WHERE `message_id` > '$last_checked_id' ");

$i = 0;
while($row = mysql_fetch_array($query)) {

    if($i == 0) {
        // set this as the last message processed
        mysql_query(" UPDATE `settings` WHERE `last_checked_id` = '". $row['message_id'] ."' ");
    }

    // only put this user in the to email list if he hasn't been added already (since there can be multiple messages for the same user but we need to notify him only once) 
    if(!in_array($row['recipient_id'], $user_emails)) {
        array_push($user_emails, $row['recipient_id']);     
    }
}
$i++;

// send email to all users at one
mail(implode(',', $user_emails), $subject, $message);

我可以将此脚本设置为 cron 并让它每小时运行一次。所有的电子邮件都是一次性发送的,邮件功能只被调用一次。唯一的缺点是用户在收到 PM 时不会立即收到通知,而是在一小时内通知一次。 但这没什么大不了的,我可以忍受。

我的问题是:

  • 是 cron 方法在性能方面明显更好还是可以忽略不计
  • 这是大多数大型网站的做法吗?还是有更好的方法,一些已建立的图书馆也许可以?

谢谢。

【问题讨论】:

  • 在 SO 上投票最多的 PHP 问题可能有一些见解 stackoverflow.com/questions/3905734/…
  • 相关:我还会限制一些电子邮件(例如线程回复通知),这样他们就不会突然收到 10 封电子邮件,都告诉他们同一个线程被评论了。

标签: php mysql performance email


【解决方案1】:

您可以在 mysql 表中插入邮件(emailoutgoing)

每“3”分钟运行一次 cron 作业,您可以从表中收到未发送的(100 封?)电子邮件,发送并将行标记为已发送。

【讨论】:

    【解决方案2】:

    如果我理解正确,您会向每个人发送完全相同的电子邮件吗?在这种情况下,您应该使用密件抄送字段作为电子邮件地址,否则每个人都会看到其他收件人,但在这种情况下,您可能会遇到反垃圾邮件引擎的问题,这些引擎可能会忽略您的电子邮件,因为他们不会将他们的用户视为电子邮件的收件人(不在在 to 或 cc 字段中)。

    但是你真的应该考虑为每个用户发送个性化的电子邮件(如果你将 sneek preview 添加到谁发送了消息和/或消息的一部分,他们会更加渴望)

    【讨论】:

    • 我同意,实际上我现在发送一封个性化的电子邮件,其中包含他们收到的消息的预览以及一个链接,以查看更多返回我的网站。我只是快速地把这个例子串起来,如果我还想发送预览,我必须扩展脚本。关于向所有用户显示其他用户的好处。我不知道 mail() 函数这样做了。
    【解决方案3】:

    首先,阅读 Mike B 评论中的链接。

    其次,您的代码有一些有趣的失败模式 - 它可能会失败,将所有邮件标记为已发送,而没有人会知道。关于 CRON 和其他无人值守流程(包括一般网站)的一个关键问题是,您需要知道何时出现问题。在您发送邮件后,我会考虑将“更新”声明放在最后。放入某种日志记录,以便您可以跟踪正在发生的事情。

    第三,请不要将这封电子邮件发送给“收件人”字段中的所有这些人 - 正如 Miro 所说,这是垃圾邮件诱饵,但它也会让用户接触到比他们应该拥有的更多信息 - 他们知道电子邮件地址您网站的随机其他用户碰巧在一小时内收到了 PM。如果你正在建立一个约会网站或社交网络,那几乎肯定会让人生气。

    最后,我工作过的其他有类似要求的网站往往有一个“事件”表,由守护进程/服务样式进程监控。守护进程会对做什么做出明智的决定。我们设计的解决方案适合在多线程甚至多台机器上运行,但实际上从来不需要这样。

    因此,您可能有一个“事件”表,如下所示:

    eventID    eventDate    eventType     eventStatus     eventMeta
    -------------------------------------------------------------------
    1          1 Feb 2012        PM           NEW         <from>bob@banana.com</from><to>alice@passionfruit.com</to>
    2          1 Mar 2012        PM           COMPLETE    <from>fred@pear.com</from><to>jennifer@avocado.com</to> 
    

    守护程序不断扫描 eventStatus 为 NEW 的记录,将它们设置为“进行中”,处理它们,然后将状态设置为完成。

    这使您可以查看系统中正在发生的事情 - 如果记录“正在进行”超过一秒钟,则说明有问题。如果“新”记录的数量不断增长,而“完整”记录的数量没有增长,那么就会出现问题。

    【讨论】:

      猜你喜欢
      • 2018-03-06
      • 1970-01-01
      • 2012-09-20
      • 1970-01-01
      • 2021-07-18
      • 2010-09-08
      • 1970-01-01
      • 2011-06-18
      • 2010-11-10
      相关资源
      最近更新 更多