web-dev-qa-db-ja.com

StackExchange.Redisタイムアウトおよび「この操作を処理するために使用できる接続がありません」

実稼働環境には次の問題があります(Webファーム-4ノード、その上にロードバランサー):

1)Timeout performing HGET key, inst: 3, queue: 29, qu=0, qs=29, qc=0, wr=0/0 at StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor``1 processor, ServerEndPoint server) in ConnectionMultiplexer.cs:line 1699これは1分間に3〜10回発生します

2)No connection is available to service this operation: HGET key at StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor``1 processor, ServerEndPoint server) in ConnectionMultiplexer.cs:line 1666

Marcが提案したように実装しようとしました(おそらく間違って解釈した)-Redisへの接続は複数よりも少ない方が良いでしょう。次の実装を行いました。

public class SeRedisConnection
{
    private static ConnectionMultiplexer _redis;

    private static readonly object SyncLock = new object();

    public static IDatabase GetDatabase()
    {
        if (_redis == null || !_redis.IsConnected || !_redis.GetDatabase().IsConnected(default(RedisKey)))
        {
            lock (SyncLock)
            {
                try
                {
                    var configurationOptions = new ConfigurationOptions
                    {
                        AbortOnConnectFail = false
                    };
                    configurationOptions.EndPoints.Add(new DnsEndPoint(ConfigurationHelper.CacheServerHost,
                        ConfigurationHelper.CacheServerHostPort));

                    _redis = ConnectionMultiplexer.Connect(configurationOptions);
                }
                catch (Exception ex)
                {
                   IoC.Container.Resolve<IErrorLog>().Error(ex);
                    return null;
                }
            }
        }
        return _redis.GetDatabase();
    }

    public static void Dispose()
    {
        _redis.Dispose();
    }
}

実際に処分は現在使用されていません。また、このような動作を引き起こす可能性のある実装の詳細がいくつかあります(ハッシュのみを使用しています):1.ハッシュの追加、削除-非同期2.取得-同期

誰かがこの動作を回避する方法を教えてもらえますか?

事前に感謝します!

解決しよう-ネットワーク機能を評価した後のクライアント接続タイムアウトの増加。

UPDATE 2:実際には問題は解決しませんでした。キャッシュボリュームが増加し始めたとき。 2GBから。その後、同じパターンを実際に見て、これらのタイムアウトは約5分ごとに発生しました。そして、フォーク操作が完了するまで、5分ごとにサイトが一定期間凍結されました。次に、x秒ごとにフォーク(ディスクに保存)を作成するオプションがあることがわかりました。

save 900 1
save 300 10
save 60 10000

私の場合、「300 10を保存」でした-少なくとも10の更新が行われた場合、5分ごとに保存します。また、「フォーク」は非常に高価になる可能性があることがわかりました。コメントされた「保存」セクションは、問題をまったく解決しました。 Redisのみを「メモリ内のキャッシュ」として使用しているため、「保存」セクションにコメントを付けることができます。永続化は必要ありません。キャッシュサーバーの「Redis 2.4.6」Windowsポートの構成は次のとおりです。 https://github.com/rgl/redis/downloads

MSOpentechのRedis Windowsポートの最近のバージョンで解決された可能性があります: http://msopentech.com/blog/2013/04/22/redis-on-windows-stable-and-reliable/ しかし、私はまだテストしていません。

とにかくStackExchange.Redisはこの問題とは何の関係もありません。MarcGravellのおかげで、本番環境ではかなり安定して動作します。

最終更新:Redisはシングルスレッドソリューションです-最終的には高速ですが、メモリを解放する時点になると(古くなったアイテムや期限切れ)1つのスレッドがメモリを再利用する必要があるために問題が発生し(これは高速な操作ではありません-どのアルゴリズムが使用されていても)、同じスレッドがGET、SET操作を処理する必要があります。もちろん、中負荷の本番環境について話しているときに起こります。メモリバリアに達したときにスレーブでクラスタを使用しても、同じ動作になります。

41
George Anisimov

ほとんどの場合、この例外はクライアントの問題のようです。 StackExchange.Redisの以前のバージョンはWin32ソケットを直接使用していましたが、これは時々悪影響を及ぼします。おそらく、Asp.netの内部ルーティングが何らかの形でそれに関連しています。
良いニュースは、StackExchange.Redisのネットワークインフラが最近完全に書き換えられたことです。最後のバージョンは2.0.513です。試してみると、問題が発生する可能性が高くなります。

1