2

I find the concept of transactions really useful when working with databases because obviously it allows you to rollback changes if one step of a modification goes awry.

Is there some way I can extend the same principle across multiple services? Say I have the following example of someone uploading something to a website (not contrived by the way, I'm dealing with something similar now):

// Store data in an object store
$object->putToS3();

// Add to ElasticSearch node
Search::indexObject($object);

// Remove local files
$object->deleteLocalFiles();

// Increment some Redis counter
Redis::hmset(...);

// Add to database
$object->save();

Is there some standardized solution on how I can undo all of these actions if any one fails, to keep my data in the correct state? I don't have much knowledge about this.

What I do know however is that it would suck to have something added to your database that doesn't exist in your storage solution or in your Redis store.

Has anyone dealt with anything similar?

marked-down
  • 155
  • 6

2 Answers2

1

The technique you're looking for is called two phase commit. Essentially, the idea is that you ask each of your services to determine whether the transaction will succeed or not, then you separately tell each of them whether or not to actually proceed with the transaction. They may have to lock resources during the preparation phase in order to ensure the transaction is still able to complete when it is committed.

Jules
  • 17,614
  • 2
  • 33
  • 63
-3

I think there is no such thing you are asking for.

I would use a simple try-catch block during the store process, and throw any exception if something goes wrong. You need to manually track the results of each suboperation, and roll-back any changes happened.

  • 2
    This isn't a good solution, because it means that the databases of some of your services may temporarily be in an impossible state. – Jules Aug 31 '15 at 06:35