防止站点范围内的双重提交

时间:2012-08-07 20:33:15

标签: php twitter submit twitter-oauth fwrite

我很难找到这个问题的好标题,所以我希望这很清楚。我目前正在我的一个网站上使用TwitterOauth模块发布推文。虽然这有效,但我需要对提交的推文数量设置限制; 每小时只有一个

注意:我没有使用数据库的选项。这对这个问题至关重要。

我在PHP文件中将此结合如下,处理实际发布到Twitter API:

# Save the timestamp, make sure lastSentTweet exists and is writeable
function saveTimestamp(){
    $myFile = "./lastSentTweet.inc";
    $fh = fopen($myFile, 'w');
    $stringData = '<?php function getLastTweetTimestamp() { return '.time().';}';
    fwrite($fh, $stringData);
    fclose($fh);
}

# Include the lastSentTweet time
include('./lastSentTweet.inc');

# Define the delay
define('TWEET_DELAY', 3600);

# Check for the last tweet
if (time() > getLastTweetTimestamp() + TWEET_DELAY) {
    // Posting to Twitter API here
} else {
    die("No.");
}
{p>(初始)lastSentTweet.inc文件的内容(chmod 777):

<?php function getLastTweetTimestamp() { return 1344362207;}

问题是,虽然这有效;它允许意外双重提交;如果多个用户(以及此脚本运行的站点当前非常繁忙)触发此脚本,则会发生2提交(或更多,但尚未发生)Twitter通过,而不仅仅是1.我的第一个想法是打开,写入和关闭文件的延迟(虽然很小),但我可能是错的。

有没有人知道什么允许意外双提交(以及如何解决这个问题)?

1 个答案:

答案 0 :(得分:1)

你正在获得竞争条件。在进行更改时,您需要在文件上实现locking,但是您需要将两者括起来(include语句)和锁内更新;重要的是确保没有其他人(例如另一个HTTP请求)正在使用该文件,同时您读取其当前值,然后使用新时间戳更新它。

这将是相当无效的。您可以在PHP安装中使用其他选项,这里有一些:

  1. 即使您没有数据库服务器,也可以使用数据库:SQLite
  2. 您可以将时间戳存储在APC中,并在更新时使用apc_cas()检测上次存储的时间戳是否仍然是最新的。
  3. <强>更新

    您的锁定工作流程必须是这样的:

    1. 获取存储时间戳的锁定。如果您正在处理文件,则需要打开文件以阅读,并在其上调用flock()。如果另一个进程已锁定文件,则flock()将挂起,并且只有在获取锁定后才会返回,此时尝试锁定文件的其他进程将挂起。
    2. 从已锁定的文件中读取存储的时间戳。
    3. 检查自存储的时间戳以来是否已经过了所需的时间。
      • 如果已通过,则发送推文并将当前时间戳保存到文件中;否则你不要触摸存储的时间戳。
    4. 释放锁定(只需关闭文件即可)。
    5. 这将确保在您读取并测试之后但在存储新时间戳之前,没有其他进程会更新时间戳。