gpt4 book ai didi

php - 避免竞争条件,但仍然能够回滚

转载 作者:可可西里 更新时间:2023-11-01 08:28:00 25 4
gpt4 key购买 nike

我有一个 MySQL 表,其中包含要发送的电子邮件。

在每次加载页面时,我都会检查是否有任何未发送的电子邮件,然后从中提取一些并发送。

为了防止两个同时加载的页面发送出同一封电子邮件,我正在考虑做这样的事情:

$pdo = new PDO(...);

// Start blocking other page loads
$pdo->beginTransaction();
$stmt = $pdo->query("SELECT id, recipient, subject, body
FROM emails WHERE sent = 0 LIMIT 1 FOR UPDATE");

$mail = $stmt->fetch();

if(false !== $mail)
$pdo->exec("UPDATE emails SET sent = 1 WHERE id = $mail['id']");

// End blocking other page loads
$pdo->commit();

if(false !== $mail) {
// Send e-mail
}

但是如果执行在提交之后但在电子邮件成功发送之前中止怎么办?电子邮件将按发送时的原样发送,但实际上并未发送。当然,我可以等到电子邮件发送后才提交,但这会导致更长的阻塞期。我通过 SMTP 发送电子邮件,发送一封电子邮件大约需要 10 秒。

您对如何解决这个问题有什么想法吗?一种选择可能是检测表是否被锁定,然后跳过这整个步骤。这可能吗?

最佳答案

如果您希望它以任何方式扩展,请为此使用队列系统(redis、beanstalkd、RabbitMQ 等)。

从长远来看,根据页面加载发送电子邮件是一个可怕的想法,因为您不是异步发送电子邮件,而是将随机用户的页面加载速度降低很多.

这是一个例子:

获取一个 redis 队列,并发布一个包含要从中发送的电子邮件 ID 的 json 字符串:

{"id":1, "job":"pending", "data": {"user": "foobar"}}

创建一个 cronjob 来订阅这个队列,并连接到数据库并发送带有这些 ID 的电子邮件。

如果出现错误,只需将作业更改为"job":"errored"。在您的电子邮件任务的下一次预定运行中,您将在那里处理它。

那里有很多队列库,在页面加载时执行异步任务是错误的方法。

关于php - 避免竞争条件,但仍然能够回滚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32988518/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com