2012-08-07 190 views
1

我很难找出这个问题的好标题,所以我希望这很清楚。我目前正在使用我的某个网站上的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.我的第一个想法是打开,写入和关闭文件(尽管很小)的延迟,但我可能是错的。

有没有人有一个想法是什么允许意外双重提交(以及如何解决这个问题)?

+2

使用db而不是文件。 – 2012-08-07 20:34:48

+0

对不起,忘了提及:我不能(加上那个问题)。否则我当然会;) – 2012-08-07 20:43:13

+0

不能想象为什么你不能使用数据库。 PHP有一个内置的 – 2012-08-07 20:46:38

回答

1

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

这将是相当无效的。你可能在你的PHP安装提供其他选择,这里有一些:

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

更新

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

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

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

+0

谢谢!这真的很有帮助。我会尽快查看这两种选择。再次感谢! – 2012-08-07 21:01:27

+0

唉,没有APC可用。我会研究SQLite,但不能被这个问题所吸引。我想到了解决这样的: 如果“saveTimeStamp”功能会发出鸣叫之前返回true,我会包括“如果”一个额外的:“如果(saveTimeStamp()){//鸣叫}”这将可能修理它? (或者至少让机会之窗更小?) – 2012-08-08 08:13:02