Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement transaction with rollback in Redis

My program needs to add data to two lists in Redis as a transaction. Data should be consistent in both lists. If there is an exception or system failure and thus program only added data to one list, system should be able to recover and rollback. But based on Redis doc, it doesn't support rollback. How can I implement this? The language I use is Java.

like image 417
Tommy Avatar asked Sep 20 '16 04:09

Tommy


People also ask

Does Redis support rollback?

This means that Redis transactions have a true serializable isolation level, and also means that no rollback mechanism is required to implement WATCH.

Does Redis support transaction?

Redis Transactions allow the execution of a group of commands in a single step, they are centered around the commands MULTI , EXEC , DISCARD and WATCH . Redis Transactions make two important guarantees: All the commands in a transaction are serialized and executed sequentially.

Why is Redis atomic?

All commands in a transaction are sequentially executed as a single isolated operation. It is not possible that a request issued by another client is served in the middle of the execution of a Redis transaction. Redis transaction is also atomic. Atomic means either all of the commands or none are processed.

Which of the following are Redis transaction commands?

For operations involving multiple keys (of the same or different types), Redis has five commands that help us operate on multiple keys without interruption: WATCH , MULTI , EXEC , UNWATCH , and DISCARD .


1 Answers

If you need transaction rollback, I recommend using something other than Redis. Redis transactions are not the same as for other datastores. Even Multi/Exec doesn't work for what you want - first because there is no rollback. If you want rollback you will have to pull down both lists so you can restore - and hope that between our error condition and the "rollback" no other client also modified either of the lists. Doing this in a sane and reliable way is not trivial, nor simple. It would also probably not be a good question for SO as it would be very broad, and not Redis specific.

Now as to why EXEC doesn't do what one might think. In your proposed scenario MULTI/EXEC only handles the cases of:

  1. You set up WATCHes to ensure no other changes happened
  2. Your client dies before issuing EXEC
  3. Redis is out of memory

It is entirely possible to get errors as a result of issuing the EXEC command. When you issue EXEC, Redis will execute all commands in the queue and return a list of errors. It will not provide the case of the add-to-list-1 working and add-to-list-2 failing. You would still have your two lists out of sync. When you issue, say an LPUSH after issuing MULTI, you will always get back an OK unless you:

  • a) previously added a watch and something in that list changed or
  • b) Redis returns an OOM condition in response to a queued push command

DISCARD does not work like some might think. DISCARD is used instead of EXEC, not as a rollback mechanism. Once you issue EXEC your transaction is completed. Redis does not have any rollback mechanism at all - that isn't what Redis' transaction are about.

The key to understanding what Redis calls transactions is to realize they are essentially a command queue at the client connection level. They are not a database state machine.

like image 122
The Real Bill Avatar answered Oct 16 '22 23:10

The Real Bill