同様の機能を持つ同様のデータベースを持つ複数のWebサイトがあります(たとえば、同じ製品を販売する店舗(1人の所有者))。
必要性:新しい製品をすべての店舗に同時に追加します。 または、少なくとも1つでエラーが発生した場合はどこにも追加しないでください。 非常に単純な場合、特定のテーブルのレコードIDはすべてのサイトで一致する必要があります。 たとえば、product_id。 繰り返しますが、タスクを単純化しました。実際、すべてがはるかに複雑です。
各サイトにProductクラスがあり、対応するメソッドがあるとします
class Product
{
...
public static function createNewProduct($productName)
{
if ( self::exists($productName) ) {
throw new Exception('product exists in database');
//
// , « - »
}
$db->execute(
'INSERT INTO products
SET name={$productName}');
$newId = $db->lastInsertId;
return new self($newId);
}
...
}
つまり、各サイトで次のように新しいエントリが作成されます。
<?php
$product = Product::createNewProduct('new product name');
いずれかのサイトで例外が発生する可能性があるため、すべてのクローンサイトでこのコードを実行する必要があります。その場合、どのサイトにもレコードを追加しないでください。
例:
beginTransaction();
try {
$product = Product::crateateNewProduct('new product name);
commitTransaction();
} catch (Exception $e) {
rollbackTransaction();
throw new Exception('clone-wide code execution failure');
}
これがどのように見えるべきかです! 問題は次のとおりです。
- すべてのクローンサイトでまったく同じコードを同時に実行する必要があります。
- commitTransaction()関数は、すべてのクローンサイトが「ゴーアヘッド」を行うまで「true」コミットを行うべきではありません。
- 少なくとも1つのクローンでrollbackTransaction()関数に入ると、すべてのサイトでエラーが発生しなくてもすべてのサイトが「ロールバック」されるように、すべてのクローンで例外をスローする必要があります。
これを行うには:
- 「分散トランザクション」をサポートする機能に、トランザクションのステータスを通知させます。 たとえば、 example1.com / transaction / status.txtのように、外部からアクセス可能な行BEGIN / READY / COMMITED / ROLLBACKを持つファイル
- MySQLトランザクションがすべての既知のクローンサイトを「実行」することを確認する前にcommitTransaction()関数を作成し、「すべてが正常」であることを確認し、この場合のみCOMMITを実行します。 そうしないと、例外がスローされます。
- rollbackTransaction()関数がstatus.txtファイルにステータスを保存するようにして、他のクローンサイトがこれを見つけて「ロールバック」できるようにします
写真はこれを示しています。
同様に、製品のステータスの変更やカードの編集など、任意のコードを実行できます。 4codeコードを渡す方法を見つける必要があるだけです。これは「すべてのクローンで同期的に」実行され、eval($コード)を呼び出す必要があります。
すべてのサイトでコードを(多かれ少なかれ)同時に実行させる方法にはまだ小さな問題があります。 nohupでこれを解決しましたが、他の方法もあると思います。
これらすべてをhabrachelovekamiと議論したいと思います。