it-swarm.com.de

StackExchange.Redis-Zeitlimit und "Für diesen Vorgang ist keine Verbindung verfügbar"

Ich habe die folgenden Probleme in unserer Produktionsumgebung (Web-Farm - 4 Knoten, darüber Load Balancer):

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 Dies geschieht 3-10 mal pro Minute

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

Ich habe versucht, wie von Marc vorgeschlagen zu implementieren (möglicherweise habe ich es falsch interpretiert) - besser weniger Verbindungen zu Redis als mehrere. Ich habe folgende Implementierung vorgenommen:

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();
    }
}

Eigentlich wird dispose gerade nicht verwendet. Außerdem habe ich einige Besonderheiten der Implementierung, die ein solches Verhalten verursachen könnten (ich verwende nur Hashes): 1. Hashes hinzufügen, entfernen - async 2. Get -sync

Könnte mir jemand helfen, dieses Verhalten zu vermeiden?

Vielen Dank im Voraus!

Gelöst - Erhöhen des Zeitlimits für die Client-Verbindung nach Auswertung der Netzwerkfähigkeiten.

UPDATE 2 : Eigentlich hat es das Problem nicht gelöst. Wenn das Cache-Volumen zuzunehmen beginnt, z. ab 2 GB. Dann habe ich dasselbe Muster gesehen, tatsächlich sind diese Timeouts etwa alle 5 Minuten aufgetreten. Und unsere Standorte wurden alle 5 Minuten für einige Zeit eingefroren, bis der Gabelbetrieb beendet war. Dann fand ich heraus, dass es eine Option gibt, alle x Sekunden einen Fork (auf Festplatte speichern) zu machen:

save 900 1
save 300 10
save 60 10000

In meinem Fall war es "save 300 10" - speichern Sie alle 5 Minuten, wenn mindestens 10 Aktualisierungen stattgefunden haben. Auch ich fand heraus, dass "Gabel" sehr teuer sein könnte. Der kommentierte Abschnitt "Speichern" löste das Problem überhaupt. Wir können den Abschnitt "Speichern" kommentieren, da wir nur Redis als "Cache im Speicher" verwenden - wir brauchen keine Ausdauer. Hier ist die Konfiguration unserer Cache-Server "Redis 2.4.6" Windows-Port: https://github.com/rgl/redis/downloads

Möglicherweise wurde es in den letzten Versionen von Redis Windows Port in MSOpentech behoben: http://msopentech.com/blog/2013/04/22/redis-on-windows-stable-and-reliable/ aber ich habe noch nicht getestet.

Trotzdem hat StackExchange.Redis nichts mit diesem Problem zu tun und funktioniert dank Marc Gravell in unserer Produktionsumgebung ziemlich stabil.

ENDGÜLTIGES UPDATE: Redis ist eine Single-Thread-Lösung - es ist letztendlich schnell, aber wenn es darum geht, den Speicher freizugeben (Entfernen von Elementen, die veraltet oder veraltet sind) Abgelaufen) Die Probleme treten auf, weil ein Thread den Speicher zurückfordern sollte (das ist keine schnelle Operation - welcher Algorithmus auch immer verwendet wird) und derselbe Thread GET- und SET-Operationen behandeln sollte. Natürlich passiert es, wenn es sich um eine mittelgroße Produktionsumgebung handelt. Auch wenn Sie einen Cluster mit Slaves verwenden, wenn die Speichergrenze erreicht ist, hat dieser das gleiche Verhalten.

41
George Anisimov

In den meisten Fällen scheint es sich bei dieser Ausnahme um ein Client-Problem zu handeln. In früheren Versionen von StackExchange.Red wurde der Win32-Socket direkt verwendet, was sich manchmal negativ auswirkt. Wahrscheinlich hängt das interne Routing von Asp.net damit zusammen.
Die gute Nachricht ist, dass die Netzwerkinfrastruktur von StackExchange.Redis kürzlich vollständig umgeschrieben wurde. Die letzte Version ist 2.0.513. Probieren Sie es aus und es besteht eine gute Chance, dass Ihr Problem behoben wird.

1