【问题标题】:Preventing a site-wide double submit防止站点范围内的双重提交
【发布时间】:2012-08-08 17:31:37
【问题描述】:

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

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

我已将其合并到处理实际发布到 Twitter API 的 PHP 文件中,如下所示:

# 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.");
}

lastSentTweet.inc 文件(chmod 777)的(初始)内容:

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

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

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

【问题讨论】:

  • 对不起,忘了提:我不能(将其添加到问题中)。否则我当然会;)
  • 无法想象你不能使用数据库的原因。 php内置了一个
  • 但这不会给我同样的问题吗?

标签: php twitter submit twitter-oauth fwrite


【解决方案1】:

你得到了比赛条件。在进行更改时,您需要在文件上实现locking,但您需要将读取(include 语句)和更新都包含在 both 内;关键是确保没有其他人(例如另一个 HTTP 请求)正在使用该文件,同时您读取它的当前值,然后用新的时间戳更新它。

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

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

更新

您的锁定工作流程需要是这样的:

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

这将确保在您读取和测试时间戳之后,但在您存储新时间戳之前,没有其他进程会更新时间戳。

【讨论】:

  • 谢谢!这真的很有帮助。我会尽快研究这两种选择。再次感谢!
  • 唉,没有可用的 APC。我将研究 SQLite,但不禁被这个问题所吸引。我想过这样解决它:如果'saveTimeStamp'函数返回true,并且我会在发送推文之前包含一个额外的'if':'if(saveTimeStamp()){ //tweet }'这可能会解决它? (或者至少让机会之窗变小?)
猜你喜欢
  • 2012-04-05
  • 2011-03-12
  • 1970-01-01
  • 2011-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多