1

この質問の良いタイトルを見つけるのに苦労していたので、これが明確であることを願っています。私は現在、自分のサイトの1つでTwitterOauthモジュールを使用してツイートを投稿しています。これは機能しますが、送信されるツイートの量に制限を設定する必要があります。1時間に1つだけ

注:データベースを使用するオプションはありません。これは質問にとって最も重要です。

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;}

問題は、これが機能している間です。偶発的な二重送信が可能です。複数のユーザー(およびこのスクリプトが実行されているサイトが現在非常に混雑している)がこのスクリプトをトリガーすると、1つだけではなく2つの送信(まだ発生していませんが、それ以上)がTwitterにスリップスルーすることがあります。これは、ファイルを開いたり、書き込んだり、閉じたりする際の(1分ではありますが)遅延ですが、間違っている可能性があります。

偶発的な二重提出を可能にするもの(およびこれを修正する方法)を誰かが知っていますか?

4

1 に答える 1

1

競合状態になっています。変更を加えている間、ファイルにロックを実装する必要がありますが、読み取り(ステートメント)と更新の両方をロック内に含める必要があります。include重要なのは、現在の値を読み取ってから新しいタイムスタンプで更新している間、他の誰も(たとえば、別のHTTPリクエスト)ファイルを使用していないことを確認することです。

これはかなり効果がありません。PHPインストールで利用できる可能性のある他のオプションがあります。ここにいくつかあります。

  1. データベースサーバーがなくてもデータベースを使用できますSQLite
  2. タイムスタンプをAPCにapc_cas()保存し、更新時に最後に保存されたタイムスタンプがまだ最新であるかどうかを検出するために使用できます。

アップデート

ロックワークフローは次のようにする必要があります。

  1. 保存されたタイムスタンプのロックを取得します。ファイルを操作している場合は、読み取りと書き込みのためにファイルを開いて、それを呼び出す必要がありますflock()flock()別のプロセスがファイルをロックしている場合はハングし、ロックを取得した後にのみ戻ります。その時点で、ファイルをロックしようとしている他のプロセスがハングします。
  2. すでにロックされているファイルから保存されているタイムスタンプを読み取ります。
  3. 保存されたタイムスタンプから必要な時間が経過したかどうかを確認します。
    • 合格した場合にのみ、ツイートを送信し、現在のタイムスタンプをファイルに保存します。それ以外の場合は、保存されているタイムスタンプに触れません。
  4. ロックを解除します(ファイルを閉じるだけで十分です)。

これにより、タイムスタンプを読み取ってテストした後、新しいタイムスタンプを保存する前に、他のプロセスがタイムスタンプを更新しないことが保証されます。

于 2012-08-07T20:57:02.227 に答える