📜 ⬆️ ⬇️

Synchronous clones or simple distributed transactions (PHP)

For a long time I tried to put into words why I needed all this, but then I refused the idea. Who is interested - I will answer in the comments. So the essence:

There are several websites with a similar database, with similar functionality (for example, stores selling the same goods (one owner).

Need: add a new product to all stores at the same time. Or add nowhere in case of an error on at least one. If it is quite simple, then the ID of records in certain tables should be the same on all sites. For example, product_id. Again, I will say - I simplified the task, in fact, everything is much more complicated.

')
Suppose there is a Product class and a corresponding method on each site.

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


That is, on each site a new entry is created as follows:

<?php
$product = Product::createNewProduct('new product name');


and we need to execute this code on all clone sites, given that an exception is possible on one of them, in which case the entry should not be added to any of the sites.

For example:

beginTransaction();

try {
$product = Product::crateateNewProduct('new product name);
commitTransaction();
} catch (Exception $e) {
rollbackTransaction();

throw new Exception('clone-wide code execution failure');
}


This is how it should look! The problem is that:

  1. exactly the same code needs to be executed simultaneously on all clone sites;
  2. The commitTransaction () function should not make a “real” commit until all clone sites “give the go-ahead”
  3. when a rollbackTransaction () function is hit on at least one of the clones, an exception should be thrown on all clones so that all sites “roll back” even if they have no errors.


For this:

  1. let's make it so that the functions for supporting “distributed transactions” report on the status of the transaction. For example, a file with the string BEGIN / READY / COMMITED / ROLLBACK is accessible from outside, for example, example1.com/transaction/status.txt
  2. let's do so that the commitTransaction () function, before confirming the MySQL transaction, “runs” through all known clone sites and checks whether “everything is in order” and only in this case executed the COMMIT. Otherwise, it would throw an exception;
  3. let's make the rollbackTransaction () function also save the status to the status.txt file so that other clone sites can learn about it and “roll back”


The picture illustrates this:

image

Similarly, you can execute any code, such as changing the product status or editing the card. You just need to find a way to pass the 4code, which you need to perform "synchronously on all clones" and call eval ($ code).

There is still a small problem - how to make the code run [more or less] simultaneously on all sites. I decided this with nohup, but I think there are other ways.

I would like to discuss all this with habrachelovekami.

Source: https://habr.com/ru/post/54414/


All Articles