我有一个包含3个节点的Redis集群; 1是主设备,其他2是从设备,持有主设备的副本。当我杀死主实例时,Redis Sentinel将另一个节点提升为主节点,它开始接受写入。
在我的测试中,我注意到一旦新主人升级,Redis中SE.Redis的第一次操作失败了:
StackExchange.Redis.RedisConnectionException:GET上的SocketFailure ---> System.IO.IOException:无法从传输连接读取数据:远程强制关闭现有连接 主办。 ---> System.Net.Sockets.SocketException:现有连接 被远程主机强行关闭
为了避免这种情况,我已经实现了如下的重试逻辑。还有更好的选择吗?
private RedisValue RedisGet(string key)
{
return RedisOperation(() =>
{
RedisKey redisKey = key;
RedisValue redisValue = connection.StringGet(redisKey);
return (redisValue);
});
}
private T RedisOperation<T>(Func<T> act)
{
int timeToSleepBeforeRetryInMiliseconds = 20;
DateTime startTime = DateTime.Now;
while (true)
{
try
{
return act();
}
catch (Exception e)
{
Debug.WriteLine("Failed to perform REDIS OP");
TimeSpan passedTime = DateTime.Now - startTime;
if (this.retryTimeout < passedTime)
{
Debug.WriteLine("ABORTING re-try to REDIS OP");
throw;
}
else
{
int remainingTimeout = (int)(this.retryTimeout.TotalMilliseconds - passedTime.TotalMilliseconds);
// if remaining time is less than 1 sec than wait only for that much time and than give a last try
if (remainingTimeout < timeToSleepBeforeRetryInMiliseconds)
{
timeToSleepBeforeRetryInMiliseconds = remainingTimeout;
}
}
Debug.WriteLine("Sleeping " + timeToSleepBeforeRetryInMiliseconds + " before next try");
System.Threading.Thread.Sleep(timeToSleepBeforeRetryInMiliseconds);
}
}
}
答案 0 :(得分:0)
TLDR:不要将Sentinel与Stackexchange.Redis一起使用,因为此客户端库中仍未实现Sentinel支持。
有关所有未解决的问题,请参阅https://github.com/StackExchange/StackExchange.Redis/labels/sentinel,现在还有一个相当不错的PR开放约1年。
话虽如此,我在重试方面也有相对较好的经验,但我绝不会在生产中使用这种方法,因为它根本不可靠。