web-dev-qa-db-ja.com

ConnectionMultiplexerはどのように切断を処理しますか?

StackExchange.Redisの 基本的な使用法 のドキュメントでは、ConnectionMultiplexerは長期間有効であり、再利用が期待されていると説明されています。

しかし、サーバーへの接続が切断された場合はどうでしょうか? ConnectionMultiplexerは自動的に再接続しますか、それとも this answer (その答えを引用)のようにコードを記述する必要がありますか?

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

上記のコードは切断からの回復を処理するのに良いものですか、それとも実際に複数のConnectionMultiplexerインスタンスが発生しますか?同じように、IsConnectedプロパティはどのように解釈すべきですか?

[余談:上記のコードは、特にマルチスレッド環境でのレイジー初期化のかなり悪い形式だと思います-参照 シングルトンに関するジョン・スキートの記事 ]。

16
Gigi

これが Azure Redis Cacheチームが推奨するパターン です。

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 <T>を使用してスレッドセーフな初期化を処理します
  • 「abortConnect = false」を設定します。これは、最初の接続試行が失敗した場合、ConnectionMultiplexerが例外をスローするのではなく、バックグラウンドで暗黙的に再試行することを意味します。
  • notはIsConnectedプロパティをチェックします。接続が切断された場合、ConnectionMultiplexerはバックグラウンドで自動的に再試行するためです。
29
Mike Harder

はい、切断された接続を修正するには、そのタイプの検証が必要です。スレッドの安全性も考慮する必要があります。これは私が通常これを行う方法です:

_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()呼び出しの結果を保存しません。

0
CyberDude