I'm using the StackExchange.Redis package as a shared store for a multi-threaded application that will in turn be running on multiple servers simultaneously...so multi-multi-threaded ;)
One of the simplest use cases I have is that I want to keep a basic count on a series of keys (i.e. KEY1=4 KEY2=7, KEY3=13, etc). And I'll have business rules in place to enforce the max permissible value allowed for a given key. So for example, say KEY1 can only ever go as high as 5...if two threads fire at exactly the same time trying to increment it, I only want to allow one of them to succeed.
I believe I can accomplish this with a transaction by first fetching the current value and then making it condition that the value hasn't changed. Will this work as I am expecting? Is there a more elegant way to do this?
public void Increment(string key) {
IDatabase db = redisConn.GetDatabase();
var val = db.StringGet(key);
int maxVal = 5;
if (Convert.ToInt32(val) < maxVal) {
var trans = db.CreateTransaction();
trans.AddCondition(Condition.StringEqual(key, val));
trans.StringIncrementAsync(key);
trans.Execute();
}
}
PS: Love this package, it's a pleasure to work with
Yes, that should work fine. But it may be both easier and more efficient to use a Lua script via ScriptEvaluate
.
Note: with your current code, you may want to check the response of Execute
and "redo from start" if false
. If a thread-race happens when moving from 2 to 3, with your current code: the update would be discarded. This wouldn't be an issue with a Lua script.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With