ConnectionMultiplexer 如何处理断开连接?

How does ConnectionMultiplexer deal with disconnects?

StackExchange.Redis 的 Basic Usage 文档解释说 ConnectionMultiplexer 是长期存在的,预计会被重复使用。

但是当与服务器的连接断开时怎么办? ConnectionMultiplexer 是否自动重新连接,或者是否有必要像 this answer 那样编写代码(引用该答案):

        if (RedisConnection == null || !RedisConnection.IsConnected)
        {
            RedisConnection = ConnectionMultiplexer.Connect(...);
        }
        RedisCacheDb = RedisConnection.GetDatabase();

上面的代码是否适合处理断开连接的恢复,或者它实际上会导致多个 ConnectionMultiplexer 实例?同样,IsConnected 属性 应该如何解释?

[旁白:我认为上面的代码是一种非常糟糕的惰性初始化形式,尤其是在多线程环境中 - 请参阅 Jon Skeet's article on Singletons]。

是的,您需要这种类型的验证才能修复断开的连接。一些线程安全也应该被考虑在内。这就是我通常这样做的方式:

private static ConnectionMultiplexer _redis;
private static readonly Object _multiplexerLock = new Object();

private void ConnectRedis()
{
    try
    {
        _redis = ConnectionMultiplexer.Connect("...<connection string here>...");
    }
    catch (Exception ex)
    {
        //exception handling goes here
    }
}


private ConnectionMultiplexer RedisMultiplexer
{
    get
    {
        lock (_multiplexerLock)
        {
            if (_redis == null || !_redis.IsConnected)
            {
                ConnectRedis();
            }
            return _redis;
        }
    }
}

然后我在需要调用 Redis 端点的任何地方使用 RedisMultiplexer 属性。我通常不存储 GetDatabase() 调用的结果,因为文档说这是一个非常轻量级的调用。

这里是 pattern recommended by the Azure Redis Cache team:

private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() => {
    return ConnectionMultiplexer.Connect("mycache.redis.cache.windows.net,abortConnect=false,ssl=true,password=...");
});

public static ConnectionMultiplexer Connection {
    get {
        return lazyConnection.Value;
    }
}

几个要点:

  • 它使用 Lazy 来处理线程安全初始化
  • 它设置 "abortConnect=false",这意味着如果初始连接尝试失败,ConnectionMultiplexer 将在后台静默重试而不是抛出异常。
  • 不会检查 IsConnected 属性,因为如果连接断开,ConnectionMultiplexer 将在后台自动重试。