Wir können einen Cache-Server zwischen unserer Anwendung und der Datenbank platzieren, um unsere Anwendungen schneller zu machen. Aber das reicht nicht aus, wenn wir unsere Anwendungen skalieren müssen. Sehen wir uns zwei Caching-Muster für eine bessere Leistung an und wie NCache setzt sie um.
Skalierbarkeit durch Datenpartitionierung
Bei der Datenpartitionierung teilen wir große Datensätze in kleinere auf und verteilen sie auf Knoten. Auf diese Weise teilen wir Lese- und Schreibvorgänge zwischen den Knoten auf und verbessern so die Gesamtleistung unserer Anwendungen. NCache unterstützt verschiedene Caching-Topologien. In diesem Zusammenhang ist eine Topologie eine Strategie zur Datenspeicherung, Replikation und Client-Konnektivität. Es gibt zwei Topologien, die die Datenpartitionierung implementieren: die Partitionierte und Partition-Replica-Topologien. In diesen beiden Topologien NCache teilt Daten in Buckets auf und platziert diese Buckets in den Knoten unseres Clusters.
NCache verwendet 1000 Buckets und verteilt diese gleichmäßig auf die Knoten in einem Cluster. Wenn wir beispielsweise einen Cache-Cluster mit einem einzelnen Knoten starten, NCache weist alle Buckets unserem einzelnen Knoten zu. Wenn wir einen weiteren Knoten hinzufügen, NCache teilt diese 1000 Buckets in zwei 500-Bucket-Knoten auf. Wenn wir außerdem einen Knoten entfernen, NCache verteilt seine Buckets auf die verbleibenden Knoten.
Da NCache unterteilt unsere Daten in Buckets und Knoten, ein Cache-Client stellt eine Verbindung zu allen Knoten her, führt jedoch Lese- und Schreibvorgänge direkt auf dem Knoten aus, der ein Element enthält. Selbst wenn ein Knoten nicht verfügbar ist, leitet ein Cache-Client unsere Anfragen mithilfe der aktiven Knoten um, um unsere Vorgänge abzuschließen. NCache Verteilt Buckets zwischen Knoten, wobei die Datengröße in jedem Knoten nahezu gleich bleibt. Auf diese Weise teilen wir nicht nur Lese- und Schreibvorgänge zwischen den Knoten auf, sondern erhöhen auch die Speicherkapazität unseres Clusters mit jedem hinzugefügten Knoten.
Dank der Datenpartitionierung skalieren Partitions- und Partitions-Replica-Topologien die Transaktionslast und die Speicherkapazität. Natürlich sind Partition und Partition-Replica nur zwei der unterstützten Topologien. NCache hat mehr Topologien mit unterschiedlichen Datenspeicher- und Replikationsstrategien. Einige von ihnen eignen sich beispielsweise für Anwendungen mit mehr Lese- oder Schreibvorgängen.
Caching-Strategien
Durch die Datenpartitionierung verbessern wir die Verfügbarkeit und Leistung unserer Anwendungen, da wir mehr Elemente in unserem Cluster zwischenspeichern können als auf einem einzelnen Server. Außerdem können wir die Leistung unserer Anwendung verbessern, indem wir auswählen, wie wir unseren Cache füllen. Es gibt zwei Strategien, um unseren Cache zu füllen: Cache-aside und Read-Through/Write-Through.
Bei der Cache-Aside-Strategie befindet sich unser Cache-Server neben unserer Datenbank. Wenn unser Cache kein Element enthält, liest unsere Anwendung es aus unserer Datenbank und speichert es im Cache. Bei dieser Strategie interagiert der Cache-Server nicht direkt mit unserer Datenbank. Wenn wir an Caching denken, kommt uns wahrscheinlich zuerst die Cache-Aside-Strategie in den Sinn.
Im Gegensatz zur Cache-Aside-Strategie funktioniert unser Cache bei den Read-Through/Write-Through-Strategien wie die Hauptdatenquelle. Hier liest unser Cache Daten aus der Datenbank und schreibt sie in sie. Daher funktionieren diese Strategien besser mit Referenzdaten, die wir häufig lesen und regelmäßig ändern, und mit Datenbankzeilen können wir sie problemlos Cache-Elementen zuordnen.
Mit Read-Through/Write-Through verschieben wir einen Teil des Datenzugriffscodes von unserer Anwendung in den Cache, wodurch unser Anwendungscode einfacher und kleiner wird. NCache unterstützt die Read-Through- und Write-Through-Caching-Strategien.
Read-Through-Caching
NCache verwendet einen benutzerdefinierten Read-Through-Anbieter, um die zugrunde liegende Datenbank aufzurufen, wenn ein Cache-Fehler auftritt. Wir können auch erzwingen NCache um die Datenbank immer zu lesen, auch wenn kein Cache-Fehler vorliegt. Unser Read-Through-Anbieter sollte das implementieren IReadThruProvider-Schnittstelle. Es enthält Methoden wie LoadFromSource machen LoadDataTypeFromSource.
Sobald wir eine haben Read-Through-Anbieter auf unserem Cache-Server bereitgestellt, entweder über NCache Manager- oder PowerShell-Skripte können wir von unseren Clientanwendungen aus verwenden, indem wir das ReadThruOptions-Objekt als Parameter an die Get-Methode übergeben, wie folgt:
1 2 3 4 5 6 7 8 9 10 11 |
// After having NCache up and running... var key = $"Product:123456"; var readThruOptions = new ReadThruOptions { Mode = ReadMode.ReadThru }; // Retrieve a cached item with Read-Thru enabled var data = cache.Get<Product>(key, readThruOptions); // Do something with the cached product here... |
Write-Through-Caching
Andererseits gilt bei der Write-Through-Strategie: NCache aktualisiert zuerst unseren Cache und erst dann unsere Datenbank. NCache kann unsere Datenbank entweder synchron oder asynchron aktualisieren. NCache ruft asynchrone Write-Through-Updates auf: Write-Behind.
Unser Write-Through-Anbieter sollte das implementieren IWriteThruProvider-Schnittstelle. Es enthält die WriteToDataSource-Methode mit Überladungen für einzelne und mehrere Elemente und Datenstrukturen. Unser Write-Through-Anbieter sollte Schreibvorgänge zum Hinzufügen, Löschen und Aktualisieren von Elementen unterstützen.
Ähnlich wie bei der Bereitstellung eines Read-Through-Anbieters müssen wir unseren bereitstellen Write-Through-Anbieter zu unserem Cache. Sobald wir unseren Anbieter in unseren Clientanwendungen bereitstellen, sollten wir die übergeben WriteThruOptions Objekt beim Einfügen von Elementen in den Cache, wie folgt:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// After having NCache up and running... var product = BuildProduct(); var key = $"Product:{product.ProductId}"; var cacheItem = new CacheItem(product); var writeThruOptions = new WriteThruOptions { Mode = WriteMode.WriteThru; } // Add an item with Write-Thru enabled cache.Insert(key, cacheItem, writeThruOptions); |
Read-Through und Write-Through helfen uns, die Skalierbarkeit und Leistung unserer Anwendungen zu verbessern. Mit Read-Through sind unsere zwischengespeicherten Elemente seitdem immer verfügbar NCache kann abgelaufene Artikel automatisch lesen. Und mit Write-through muss unsere Anwendung seitdem nicht mehr auf Datenbankschreibvorgänge warten NCache kann unsere Datenbank asynchron aktualisieren und sogar mit einem Drosselungsmechanismus den Druck auf unsere Datenbank verringern.
Zusammenfassung
Dies sind zwei Caching-Muster für bessere Leistung und Skalierbarkeit: Datenpartitionierung und Caching-Strategien. Wir können benutzen NCache um sie in unseren Anwendungen zu implementieren. Mit der Datenpartitionierung teilen wir Lese- und Schreibvorgänge zwischen Knoten auf und erhöhen die Speicherkapazität unseres Caches. Wir haben NCache Partition- und Partition-Replica-Topologien dafür. Und mit Read-Through/Write-Through machen wir unseren Cache-Server zur Datenquelle und entlasten so unsere Datenbank.
Weitere Informationen zur Datenpartitionierung und zum Durchlesen/Durchschreiben finden Sie in diesen beiden Anleitungen: Partitionierte und Partitionsreplikat-Topologien machen Anbieter von Datenquellen für Cache. Wenn Sie diese beiden Caching-Muster zur Skalierung Ihrer Anwendungen nutzen möchten, geben Sie Folgendes an NCache ein Versuch.