James
James

Reputation: 763

Redis & Java in a multithreaded application help!

We have an application which is currently threaded (about 50 threads) to process transactions.

We have setup a redis database and using DECRBY to deduct credits from a users account.

Here is an example of the process:

1. Get amount of credits for this transaction
2. Get current credit amount from from Redis: GET <key>
3. If amount of credits exceeds amount cost of transaction continue
4. DECRBY the transaction amount from Redis.

The issue i have here is obvious, when the users credits reaches 0, it does fail the transaction (good), but it lets about 10-20 transactions through because of the threading.

I have thought of setting up WATCH, MULTI, EXEC with Redis, and then retry, but won't this cause a bottleneck (I think its called race conditions) because the threads will be constantly fighting to complete the transaction.

Any suggestions ?

Upvotes: 1

Views: 3584

Answers (3)

Nikita Koksharov
Nikita Koksharov

Reputation: 10813

You could try to use Redis based Lock object implementation for Java provided by Redisson framework instead of retrying with WATCH-MULTI commands. Working with WATCH-MULTI involves unnecessary requests to Redis during each attempt which works much slower than already acquired lock.

Here is the code sample:

Lock lock = redisson.getLock("transationLock");
lock.lock();
try {
  ... // instructions
} finally {
   lock.unlock();
}

Upvotes: 0

Kshah
Kshah

Reputation: 81

Locking is what you need. Since DB locks are expensive, you can implement a simple locking scheme in Redis using SETNX and also avoid race conditions. It's well explained here - http://redis.io/commands/setnx. But you still need to implement retries at application level.

Upvotes: 2

Enno Shioji
Enno Shioji

Reputation: 26882

It isn't the most conventional way of doing it IMO (most usual way is probably to use a lock in a RDBMS), but using WATCH, MULTI, EXEC looks akin to CAS and it doesn't seem too weird to me.

I'd assume that the author of Redis intended WATCH to be used like this. Performance implication obviously depends on how this thing is implemented (which I don't know), but my bet is that it will perform pretty good.

This is because it seems likely that there will be very less to almost no contention for the same keys in your situation (what is the chance of a user frantically issuing transactions for him/herself?), the success rate for the first swap operation will be really good. So the retry will only happen in very rare cases. Since Redis seems to be a credible framework, they also probably know what they are doing (i.e. less contention = easy job for Redis, thus it can probably handle it!).

Upvotes: 0

Related Questions