我有一个将图片发布到Facebook个人资料的脚本。它需要很长时间,通常在完成之前崩溃。我需要做的是从cron作业运行多个版本的脚本,同时进行多次处理,以便更快地发布。
我的问题我希望同时运行多个脚本以加快发布速度。 选择一个用户,并更新为已发送。但是,我需要确保脚本不会同时处理两个用户,或者从数据库中选择同一个用户两次,而另一个用户可能正在处理运行脚本,从而导致在用户墙上发布两张照片。
我的问题涉及调用数据库的效率,并创建一种在此数据库上同时运行多个脚本以提高后期速度的方法。
我有一个名为tweetSent的字段,它设置为notSent。发布照片后,它会更新为“已发送”。但是每个帖子需要将近7秒钟,如果另一个脚本在处理一个用户时访问了数据库,它会在该用户墙上发布双重帖子,因为表中的字段仍然是“notSent”
我的代码说选择tweetSent为'notSent'的用户。我有一个想法可以解决我的问题。我正在考虑立即更新它以“发送”,因此同时运行的另一个多个cron作业将选择此用户。然后,当它完成发布时,它将更新为“已发送”。
我还看到了我的代码的另一个问题。它似乎同时SELECT所有用户,然后运行WHILE LOOP并从此循环发布。在我看来,也许我应该选择“tweetSent”为“notSent”的一个用户,然后立即将其更新为“发送”,然后在发送时将其更新为已发送。也许可以将这个单一调用放入函数中的数据库并在while循环中调用该函数?不确定。
我对Stack上所有伟大的编码员的问题是,我想知道这是否是最好的方法来做到这一点,或者有人知道一种更好,更有效的方法来做我想要实现的目标。
下面是我目前脚本的数据库部分,它运行得非常慢,并且不允许我在没有双重帖子的情况下运行此脚本的多个版本。
$query = "SELECT * FROM `user` WHERE tokenExpireDate > \"$date\" AND tweetSent='notSent' ";
$retval = mysql_query($query) or die("MySQL Error: ".mysql_error());
while($row = mysql_fetch_array($retval))
{
PostPhoto($fbId, $access_token);
PostText($fbId, $access_token);
echo "<hr>";
$query = "UPDATE user SET tweetSent='sent' WHERE fbID='$fbId'";
mysql_query($query) or die("MySQL Error: ".mysql_error());
}
更新:
我想出了一个'潜在的'解决方案。这会起作用还是这种愚蠢? 当我在3个不同的窗口中同时运行脚本时,我似乎工作了 它只按顺序运行它们,不能同时连接到数据库。好像。
$query = "SELECT * FROM `user` WHERE tokenExpireDate > \"$date\" AND tweetSent='notSent' LIMIT 5";
$retval = mysql_query($query) or die("MySQL Error: ".mysql_error());
while($row = mysql_fetch_array($retval))
{
$ID[] = $row['fbID'];
}
echo count($ID);
for($i=0; count($ID)>$i;$i++)
{
sendTweet($ID[$i]);
}
function sendTweet($ID)
{
// QUES THE USER ID
$query = "SELECT * FROM `user` WHERE tokenExpireDate > \"$date\" AND tweetSent='notSent' AND fbID = '$ID' LIMIT 7";
$retval = mysql_query($query) or die("MySQL Error: ".mysql_error());
if (mysql_num_rows($retval) >= 1 )
{
$query = "UPDATE user SET tweetSent='sending' WHERE fbID='$ID'";
mysql_query($query) or die("MySQL Error: ".mysql_error());
while($row = mysql_fetch_array($retval))
{
$fbId = $row['fbID'];
$type = $row['type'];
$access_token = $row['longToken'];
PostPhoto($fbId, $access_token);
PostText($fbId, $access_token);
/// UPDATES TO SENT
$query = "UPDATE user SET tweetSent='sent' WHERE fbID='$fbId'";
mysql_query($query) or die("MySQL Error: ".mysql_error());
}
}
}
答案 0 :(得分:1)
一些建议:
curl_mulit_exec()
或类似的方法同时对Facebook进行多次调用。我在PHP中设置了一个简单的REST客户端类,我已经设置了这样做。您可以随意使用它,或者只是查看curl_multi_exec()
的实现,以了解如何执行此操作。这是链接 - https://github.com/mikecbrant/php-rest-client curl_multi_exec()
一次向Facebook发送10个帖子,您可以从数据库中一次选择10行,为这些行制作10个并行的Facebook请求,将发布结果更新为这些行,然后转到下一组记录答案 1 :(得分:0)
最佳解决方案是将照片发布系统更改为message queue,因为它听起来非常像一个。
IronMQ是一个很好的起点,是最容易使用的,从那里你可以探索其他队列系统。你也获得了很好的免费等级。其他的是RabbitMQ和Amazon SQS。
队列通过从队列中删除或“弹出”消息然后处理来解决您的问题。如果发生错误或无法处理消息,则将其重新放回队列。
通过将其从队列中删除,您可以确保没有其他进程可以访问它。
您可能还想查看Gearman。
如果您不想将系统更改为队列系统,那么您需要查看事务并记录锁定。将记录设置为processing
可以允许两个进程同时提取记录,然后一个接一个地将其更新为processing
,从而导致两个进程都发布了照片。
答案 2 :(得分:-1)
单
private static $MysqlAdapter;
private $con;
private function __construct() {
$this->con = new mysqli(DB_SERVER, DB_USER, DB_PW, DB_DB);
if ($this->con->connect_errno) {
echo "Failed to connect to MySQL: (" . $this->con->connect_errno . ") " . $this->con->connect_error;
} else {
$this->con->set_charset("utf8");
}
}
public static function getInstance() {
if (self::$MysqlAdapter == NULL) {
self::$MysqlAdapter = new MysqlAdapter();
}
return self::$MysqlAdapter;
}