18

I used Only Redis as my DB, and my client is ServiceStack.Redis. The thing is, if two concurrent request need to update one key, then it can be a race condition. For example

A:

  1. int a = Get key
  2. MULTI
  3. a = a - 100
  4. Set key a
  5. EXEC

B:

  1. int a = Get key
  2. MULTI
  3. a = a - 100
  4. Set key a
  5. EXEC

if the origin "key" is 1000. If speration A and B are serialized, the right results of this two operations of "key" will be 800. But if A and B happens in the same time. Before A can commit, Operation B get value 1000 from "key", and set 900 to "key". That's not what I want. How can I prevent this kind of race conditions, use "WATCH"?

NoobEditor
  • 15,563
  • 19
  • 81
  • 112
Allan Yang
  • 181
  • 1
  • 1
  • 4

2 Answers2

20

You should read the docs on Transactions in Redis, transactions in Redis is essentially batching multiple operations so they're executed as a single atomic operation.

Since it's only batching operations, you cannot perform any reads within the context of a transaction. Any reads you need before hand need to be retrieved before the start of the transaction. You can then use the Redis WATCH to watch for any keys that shouldn't be modified before your transaction completes, if a key was modified the transaction will fail and no operations will be processed.

mythz
  • 141,670
  • 29
  • 246
  • 390
  • Thanks for reminding me that. In my program, I read before starting a transaction in my program. I have changed my pseudo code to a right order. So, WATCH should solve my problem? – Allan Yang Feb 14 '15 at 08:58
  • @AllanYang Yes using WATCH before any reads will ensure the transaction wont be executed if the key was modified before the transaction has executed. – mythz Feb 14 '15 at 09:04
0

@NoobEditor No, just using watch will not help you with a race condition. Watch-exec will guarantee that the entire batch will run iff the watched key is not updated by someone else.

Make use of Redis distributed locks to handle race conditions correctly.

shmsr
  • 3,802
  • 2
  • 18
  • 29
Ritesh
  • 1
  • 1