How to implement transaction with rollback in Redis

后端 未结 2 1893
感动是毒
感动是毒 2021-01-13 12:58

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 onl

相关标签:
2条回答
  • 2021-01-13 13:28

    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.

    0 讨论(0)
  • 2021-01-13 13:42

    Redis transactions are different. It guarantees two things.

    1. All or none of the commands are executed
    2. sequential and uninterrupted commands

    Having said that, if you have the control over your code and know when the system failure would happen (some sort of catching the exception) you can achieve your requirement in this way.

    1. MULTI -> Start transaction
    2. LPUSH queue1 1 -> pushing in queue 1
    3. LPUSH queue2 1 -> pushing in queue 2
    4. EXEC/DISCARD

    In the 4th step do EXEC if there is no error, if you encounter an error or exception and you wanna rollback do DISCARD.

    Hope it makes sense.

    0 讨论(0)
提交回复
热议问题