Redis
 sql >> Datenbank >  >> NoSQL >> Redis

Stapelüberlauf, Redis und Cache-Invalidierung

Ich kann mich ehrlich gesagt nicht entscheiden, ob dies eine SO-Frage oder eine MSO-Frage ist, aber:

Ein Wechsel zu einem anderen System ist nie möglich schneller als das Abfragen des lokalen Speichers (solange er verschlüsselt ist); einfache Antwort:Wir verwenden beides! Also verwenden wir:

  • lokaler Speicher
  • andernfalls Redis prüfen und lokalen Speicher aktualisieren
  • andernfalls von der Quelle abrufen und Redis und lokalen Speicher aktualisieren

Dies führt dann, wie Sie sagen, zu einem Problem der Cache-Invalidierung - obwohl das eigentlich nicht kritisch ist an den meisten Orten. Aber dafür - Redis-Ereignisse (Pub/Sub) ermöglichen eine einfache Möglichkeit, Schlüssel, die sich ändern, an alle Knoten zu übertragen, damit sie ihre lokale Kopie löschen können - was bedeutet:Das nächste Mal, wenn sie benötigt wird, holen wir die neue Kopie von Redis ab . Daher übertragen wir die Schlüsselnamen, die sich ändern, gegen einen einzelnen Ereigniskanalnamen.

Tools:Redis auf Ubuntu-Server; BookSleeve als Redis-Wrapper; protobuf-net und GZipStream (je nach Größe automatisch aktiviert / deaktiviert) für Paketierungsdaten.

Also:Die redis pub/sub-Ereignisse werden verwendet, um den Cache für einen bestimmten Schlüssel von eins ungültig zu machen Knoten (derjenige, der weiß, dass sich der Zustand geändert hat) sofort (so ziemlich) auf alle Knoten.

In Bezug auf unterschiedliche Prozesse (aus Kommentaren:"Verwenden Sie ein gemeinsames Speichermodell für mehrere unterschiedliche Prozesse, die dieselben Daten speisen?"):Nein, das tun wir nicht. Jede Web-Tier-Box hostet wirklich nur einen Prozess (einer gegebenen Stufe), mit Mandantenfähigkeit innerhalb das, also könnten wir innerhalb desselben Prozesses 70 Seiten haben. Aus Legacy-Gründen (z. B. "es funktioniert und muss nicht repariert werden") verwenden wir hauptsächlich den http-Cache mit der Site-Identität als Teil des Schlüssels.

Für die wenigen sehr datenintensiven Teile des Systems haben wir Mechanismen, um auf der Festplatte zu bleiben, damit das In-Memory-Modell zwischen aufeinanderfolgenden App-Domains weitergegeben werden kann, wenn das Web auf natürliche Weise recycelt (oder neu bereitgestellt) wird, aber das ist es nichts mit Redis zu tun.

Hier ist ein ähnliches Beispiel, das nur die breite Variante zeigt wie dies funktionieren könnte - drehen Sie eine Reihe von Instanzen des Folgenden auf und geben Sie dann einige Schlüsselnamen ein:

static class Program
{
    static void Main()
    {
        const string channelInvalidate = "cache/invalidate";
        using(var pub = new RedisConnection("127.0.0.1"))
        using(var sub = new RedisSubscriberConnection("127.0.0.1"))
        {
            pub.Open();
            sub.Open();

            sub.Subscribe(channelInvalidate, (channel, data) =>
            {
                string key = Encoding.UTF8.GetString(data);
                Console.WriteLine("Invalidated {0}", key);
            });
            Console.WriteLine(
                    "Enter a key to invalidate, or an empty line to exit");
            string line;
            do
            {
                line = Console.ReadLine();
                if(!string.IsNullOrEmpty(line))
                {
                    pub.Publish(channelInvalidate, line);
                }
            } while (!string.IsNullOrEmpty(line));
        }
    }
}

Was Sie sehen sollten, ist, dass, wenn Sie einen Schlüsselnamen eingeben, dieser sofort in allen laufenden Instanzen angezeigt wird, die dann ihre lokale Kopie dieses Schlüssels ausgeben würden. Offensichtlich müssten die beiden Verbindungen im realen Gebrauch irgendwo platziert und offen gehalten werden, so würde es nicht sein in using sein Aussagen. Wir verwenden dafür fast einen Singleton.