1

ジョブを実行するためにフェッチされるテーブルに多くのエントリがあります。これは、複数のサーバーにスケーリングされます。

サーバーが一連の行をフェッチして独自のジョブ キューに追加するときは、他のサーバーがフェッチしないように「ロック」する必要があります。更新が実行されると、タイムスタンプが増加し、「ロック解除」されます。

私は現在、ジョブサーバーのIDでデフォルトでnullに設定されているテーブルの「ジョブサーバー」と呼ばれるフィールドを更新することでこれを行っています。

ジョブ サーバーは、フィールドが null の行のみを選択します。

すべての行が処理されると、タイムスタンプが更新され、最後にジョブ フィールドが再び null に設定されます。

だから私はこれを同期する必要があります:

$jobs = mysql_query("
SELECT itemId 
FROM items 
WHERE 
jobserver IS NULL 
AND 
DATE_ADD(updated_at, INTERVAL 1 DAY) < NOW()
LIMIT 100
");

mysql_query("UPDATE items SET jobserver = 'current_job_server' WHERE itemId IN (".join(',',mysql_fetch_assoc($jobs)).")");

// do the update process in foreach loop
// update updated_at for each item and set jobserver to null

すべてのサーバーは上記を無限ループで実行します。フィールドが返されない場合、すべてが 2 日付 (最後の更新が 24 時間以内) であり、10 分後に送信されます。

私は現在 MyIsam を持っていますが、私の場合は innodb よりもパフォーマンスがはるかに優れていたので、そのまま使用したいと思っていますが、innodb には ACID トランザクションがあると聞きました。

そのため、選択と更新を1つとして実行できました。しかし、それはどのように見えて機能するのでしょうか?

問題は、他のプロセスが読み取り/書き込みを行う必要があり、ロックできないため、テーブルなどをロックする余裕がないことです。

また、共有セマフォなどのより高いレベルのソリューションにもオープンです。問題は、同期が複数のサーバーにまたがる必要があることです。

  • アプローチは一般的に正気ですか?あなたはそれを違うようにしますか?

  • ジョブ selectino を同期して、2 つのサーバーが同じ行を更新しないようにするにはどうすればよいですか?

4

2 に答える 2

2

最初に UPDATE を実行できますが、SELECT で使用した WHERE と LIMIT を使用します。次に、jobserver フィールドがサーバーに設定されている行を選択します。

于 2011-02-16T16:44:28.080 に答える
1

テーブルをロックする余裕がない場合は、行が変更されていないことを条件として更新を行います。何かのようなもの:

$timestamp = mysql_query("SELECT DATE_SUB(NOW(), INTERVAL 1 DAY)");

$jobs = mysql_query("
SELECT itemId 
FROM items 
WHERE 
jobserver IS NULL 
AND 
updated_at < ".$timestamp."
LIMIT 100
");

// Update only those which haven't been updated in the meantime
mysql_query("UPDATE items SET jobserver = 'current_job_server' WHERE itemId IN (".join(',',mysql_fetch_assoc($jobs)).") AND updated_at < ".$timestamp);

// Now get a list of jobs which were updated
$actual_jobs_to_do = mysql_query("
SELECT itemId
FROM items
WHERE jobserver = 'current_job_server'
");

// Continue processing, with the actual list of jobs

次のように、select クエリと update クエリを組み合わせることもできます。

mysql_query("
UPDATE items
SET jobserver = 'current_job_server'
WHERE jobserver IS NULL
AND updated_at < ".$timestamp."
LIMIT 100
");
于 2011-02-16T16:44:47.547 に答える