I'm using Stackexchange.Redis on a cluster ASP.Net Core servers, and having some trouble with transactions.
The following code is supposed to delete a field with the key "hashItemID" from two hashes, "HashA" and "HashB", but only if it exists in both:
var hashAKey = "HashA";
var hashBKey = "HashB";
var id = "hashItemID";
var tran = redis.Database.CreateTransaction();
// Only delete the item if it exists in both hashes
var hashBCondition = tran.AddCondition(Condition.HashExists(hashBKey, id));
var hashACondition = tran.AddCondition(Condition.HashExists(hashAKey, id));
tran.HashDeleteAsync(hashBKey, id);
tran.HashDeleteAsync(hashAKey, id);
var deleted = await tran.ExecuteAsync();
if (!deleted)
{
logger.LogWarning("Failed to delete '{ID}'. HashAResult: {A}, HashBResult: {B}", id, hashACondition.WasSatisfied, hashBCondition.WasSatisfied);
}
Occasionally this code will fail with the log:
Failed to delete 'hashItemID'. HashAResult: True, HashBResult: True
I was under the impression that transactions only fail if their conditions aren't met, is that true?
Looking at network and performance metrics, there's no timeouts or high memory usage that could be contributing to this.
EDIT: Unfortunately at higher loads this approach started to fall apart. Sometimes a transaction would require 50 attempts, hurting performance and taking a long time. Still looking for a better solution.
I implemented a workaround that does a good enough job.
In the case of !deleted && hashACondition.WasSatisfied && hashBCondition.WasSatisfied
I just immediately retry the deletion, up to 4 times.
According to tests, this has mostly fixed it. Of 6000 attempts, 430 needed to be retried once, 62 needed to be retried twice, etc.
This still seems like a bug in redis or stackexchange.redis to me though. It would be nice to hear from someone who knows better than me!
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