避免在不同实例中多次执行一个函数
Posted
技术标签:
【中文标题】避免在不同实例中多次执行一个函数【英文标题】:Avoid multiple executions of a function in different instances 【发布时间】:2022-01-09 22:19:33 【问题描述】:场景
我已经构建了一个彩票作为 wordpress 插件。用户自行注册,并在第二天第一次调用该网站时,获胜者将被插件切成小块。之后,获胜者将保存在表格中。
要重新开始切块,插件会在表格中查找当天是否有获胜者,如果找到获胜者则应退出。
这个机制确实适用于我的所有测试和几天的生产,但现在由于某种原因,该插件在 3 秒的时间跨度内产生了 15 个获胜者。日志显示没有错误。我已将所有数据复制到我的暂存环境中,但无法重现该行为。
可能发生的事情
我猜服务器负载不足(共享主机),并且有几个 wordpress 实例开始切块。在第一个进程将获胜者写入数据库后,切割停止。
可能的解决方案
我可以将文件写入文件系统以避免对数据库进行耗时的查询,以便其他实例知道正在进行切块并退出该函数。
如果我走在正确的轨道上或者我的想法有误,我会很高兴得到任何建议。
我复制了下面的关键函数。
启动插件
$from = "2021-12-01 00:00:00";
$to = "2021-12-25 23:59:59";
$lottery = new Controller($from, $to);
控制器
class Controller
private $_from;
private $_to;
public function __construct($from, $to)
$this->_from = new \DateTime($from, new \DateTimeZone("Europe/Berlin"));
$this->_to = new \DateTime($to, new \DateTimeZone("Europe/Berlin"));
add_action('init', array($this,'init'));
public function init()
$day = +date("j");
$day--;
$lastDiceDay = Model::getLastDiceDay();
if ($lastDiceDay >= $day)
return;
$dateDay = new \DateTime($this->_from->format('Y-m') . "-$day");
$mails = Model::getMailsByDay($dateDay);
$winners = $this->dice($mails, $day);
Model::saveWinner($winners, $day);
$this->mail($winners, $day);
...
模型函数
class Model
public static function getLastDiceDay()
global $wpdb;
$result = $wpdb->get_results('SELECT MAX(day_of_lottery) FROM ' . $wpdb->prefix . 'lottery', ARRAY_A);
if ($result)
return +reset($result[0]);
else
return null;
public static function saveWinner($winners, $day)
global $wpdb;
$count = count($winners);
while ($count--)
$winner = $winners[$count]->mail;
$row = ["winner_mail" => $winner["mail"], "time" => date('Y-m-d H:i:s'), "day_of_lottery" => $day, "email_log_id" => $winner["id"]];
$wpdb->insert( $wpdb->prefix . 'lottery', $row );
...
【问题讨论】:
flock() 或 sem_acquire() 的文档可能会有所帮助。 @Matt Raines:信号量听起来很有希望。非常感谢。 【参考方案1】:一个简单的解决方法是使用每天运行一次的计划任务(例如通过 cron)并抽出获胜者。
它可能是您公开的 ajax 端点(然后使用服务每天向它发出请求)、Wordpress 任务(需要在 cron 任务中运行 wp_cron 以避免像您一样的竞争条件)或文件在从 cron 任务调用的 WP 根目录中。
这样,您就不必依赖访问您网站的人来触发重要功能。它甚至可以在没有交通的情况下在早上 5 点运行。
【讨论】:
以上是关于避免在不同实例中多次执行一个函数的主要内容,如果未能解决你的问题,请参考以下文章