问题
I'm trying use Redis INCR and the incremented value to be used as a field in a Hash from C# using StackExchange.Redis. This question points similar to what I need, but in Node.
The below is something like I need.
ITransaction transation = m_connection.GetDatabase()
.CreateTransaction();
Task<long> incrementTask = transation.StringIncrementAsync(sequenceNumberRedisKey);
if (await transation.ExecuteAsync())
{
long sequenceNumber = await incrementTask;
await transation.HashSetAsync(responseRedisKey, sequenceNumber, response);
}
Note that sequenceNumber
is the result of the first operation I intend to do in the transaction.
The code seems like the transaction executes and commits before I even do any of my operations.
- Is this the way to do multiple operations in one transaction?
- Is this the way I could use the result of operation 1 (StringIncrementAsync) in operation 2 (HashSetAsync) ?
- How do I rollback the sequence number increment if HashSetAsync returns false?
- Why is there no explicit commit?
回答1:
There is a fundamental feature of redis MULTI/EXEC units that means you cannot get results during the operation. As such, there are two common ways of doing what you ask:
- Use Lua (
ScriptEvaluate[Async]
); a Lua script executes on the server start-to-end, is efficient, and avoids all problems associated with round-trip time (latency or bandwidth) or competition from other connections - Use an optimistic loop that reads the current value, then creates a transaction in SE-Redis that adds a constraint that the value you just read is the same, and execute the side-effects inside the transaction; the library will co-ordinate the necessary WATCH etc machinery to make this robust, but if the constraint condition turns out to be invalid (i.e. the library returns
false
), you need to redo everything from the start
Frankly, these days I would always guide people to option 1; option 2 is only "appealing" (and I use that term quite incorrectly) if server-side Lua scripting is not available.
I'm not at a PC, but I'm guessing the script would look something like:
local id = redis.call("incr", KEYS[1])
redis.call("hset", KEYS[2], tostring(id), ARGV[1])
return id
来源:https://stackoverflow.com/questions/63945465/redis-c-sharp-using-incr-value-in-a-transaction