2012-08-07 188 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