【问题标题】:Recover connection when a new master is elected in the cluster在集群中选出新的主节点时恢复连接
【发布时间】:2026-02-02 10:00:01
【问题描述】:

我有一个有 3 个节点的 Redis 集群; 1个是master,另外2个是slave,持有master的replica。当我杀死主实例时,Redis Sentinel 将另一个节点提升为主实例,它开始接受写入。

在我的测试中,我注意到一旦新的 master 被提升,使用 SE.Redis 在 Redis 中的第一个操作失败:

StackExchange.Redis.RedisConnectionException:GET 上的 SocketFailure ---> System.IO.IOException: Unable to read data from the transport connection: 现有连接被远程强制关闭 主持人。 ---> 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);
        }
    }
}

【问题讨论】:

    标签: redis stackexchange.redis


    【解决方案1】:

    TLDR:不要将 Sentinel 与 Stackexchange.Redis 一起使用,因为此客户端库中仍未实现 Sentinel 支持。

    请参阅https://github.com/StackExchange/StackExchange.Redis/labels/sentinel 了解所有未解决的问题,还有一个相当不错的 PR 已开放约 1 年。

    话虽如此,我在重试方面也有相对较好的经验,但我永远不会在生产中使用这种方法,因为它根本不可靠。

    【讨论】:

      最近更新 更多