我尝试通过代码进行调试,主要是当多个客户端试图在事务中修改相同的密钥时,它似乎重新调用。重试事务通常会消除错误,但是有没有理由首先抛出异常?
我正在尝试执行的代码非常简单:
var existingValue = db.HashGetAsync(hashKey, field);
var t = db.CreateTransaction();
t.AddCondition(Condition.HashEqual(hashKey, field, existingValue));
t.HashSetAsync(hashKey, field, newValue, flags: CommandFlags.FireAndForget);
bool succeeded = await t.ExecuteAsync(); // StackExchange.Redis.RedisConnectionException thrown intermittently
答案 0 :(得分:1)
当您尝试同时从2个不同的线程更新相同的密钥时,会发生此异常。如果您为每个应用程序使用一个ConnectionMultiplexer(如推荐的那样),则仅当从不同的应用程序或主机访问密钥时才会出现。
当您以事务方式更新值时,如果更新失败,则应重试(transaction.ExecuteAsync()返回false或"对EXEC的意外响应:MultiBulk:0项"抛出异常)。
这是一个以事务方式更新字符串值的方法:
public async Task<string> UpdateValueAsync(string key, Func<string, string> updateAction)
{
for (int i = 0; i < UpdateRetryCount; i++)
{
var oldValue = await database.StringGetAsync(key);
if (oldValue.IsNull)
throw new InvalidOperationException(string.Format("Key \"{0}\" not found.", key));
var newValue = updateAction(oldValue);
var transaction = database.CreateTransaction();
transaction.AddCondition(Condition.StringEqual(key, oldValue));
transaction.StringSetAsync(key, newValue);
try
{
if (await transaction.ExecuteAsync())
{
return newValue;
}
}
catch (RedisConnectionException exception)
{
if (exception.Message != "Unexpected response to EXEC: MultiBulk: 0 items")
{
throw;
}
}
}
throw new InvalidOperationException(string.Format("Failed to update value in key {0}.", key));
}