SDD 2017 London

Skalierung von .NET-Anwendungen mit verteiltem Caching

Von Iqbal Khan
Präsident & Technologie-Evangelist

Wenn Ihr Datentransaktionsvolumen, Sitzungsvolumen oder die Objektgröße zunimmt, ist dieser Vortrag genau das Richtige für Sie. Erfahren Sie, wie Sie die App-Leistung mithilfe eines verteilten Caches zwischen Ihren Apps und Ihrer Datenbank steigern. Dieser Vortrag behandelt:

  • Schneller Überblick über Skalierbarkeitsengpässe in .NET-Anwendungen
  • Beschreibung des verteilten Caching und wie es Leistungsprobleme löst
  • Wo können Sie verteiltes Caching in Ihren Anwendungen verwenden?
  • Einige wichtige Funktionen in einem verteilten Cache
  • Praktische Beispiele mit einem verteilten Cache

Überblick

Hallo zusammen, mein Name ist Iqbal Khan. Ich bin ein Technologie-Evangelist bei Alachisoft. Wir sind die Macher von NCache. Wie viele Leute haben davon gehört NCache Vor? Gute, gute Nummer. Das heutige Thema ist die Skalierung von .NET-Anwendungen mit verteiltem Caching. Es geht nicht um NCachegeht es um das allgemeine Skalierbarkeitsproblem, mit dem .NET-Anwendungen konfrontiert sind, und darum, wie dieses Problem gelöst werden kann.

Ich bevorzuge eine interaktivere Diskussion. Anstatt also bis zum Ende zu warten, um Fragen zu stellen, heben Sie bitte Ihre Hand, wenn Sie während meines Gesprächs eine Frage haben. Ich werde eine Kombination aus Architektur- und dann tatsächlichem Code durchgehen und es Ihnen auch zeigen NCache als Beispiel dafür, wie ein Cache aussieht.

Was ist Skalierbarkeit?

Lassen Sie uns also ein paar Definitionen klären. Ich bin mir sicher, dass die meisten von Ihnen das bereits wissen, aber was ist Skalierbarkeit? Skalierbarkeit ist nicht gleichbedeutend mit der Anwendungsleistung. Es handelt sich um die Anwendungsleistung bei Spitzenlasten. Wenn Sie also eine Anwendung haben, die mit 5 Benutzern superschnell läuft, ist sie nicht unbedingt skalierbar, es sei denn, sie läuft mit 5,000 oder 50,000 oder 500,000 Benutzern superschnell. Wenn Ihre Anwendung bei 5 Benutzern nicht schnell läuft, haben Sie natürlich andere Probleme als die Skalierbarkeit.

Lineare Skalierbarkeit vs. nichtlineare Skalierbarkeit

Bei der linearen Skalierbarkeit handelt es sich eher um eine Bereitstellungsarchitektur. Ist Ihre Anwendung so konzipiert, dass Sie in einer Umgebung mit Lastausgleich weiterhin weitere Server hinzufügen können und mit dem Hinzufügen weiterer Server die Transaktionskapazität erhöht wird? Wenn ich das Wort Skalierbarkeit verwende, meine ich übrigens die Skalierbarkeit von Transaktionen, nicht die Daten der Skalierbarkeit. Wir sprechen hier nicht von riesigen Datenmengen. Wir sprechen hier nicht von Terabytes oder Petabytes an Daten. Wir sprechen von viel Aktivität. Wenn Ihre Anwendung also so konzipiert ist, dass Sie weitere Server hinzufügen können und Ihre Kapazität mit dem Hinzufügen weiterer Server linear zunimmt, sind Sie linear skalierbar.

Wenn nicht, dann haben Sie eher eine logarithmische Kurve. Für diejenigen unter Ihnen, die sich noch an ihre Berechnungen aus dem College erinnern, und das Problem mit dieser Kurve ist, dass Sie einen Anstieg sehen werden, aber ab einem bestimmten Punkt bringt das Hinzufügen weiterer Server tatsächlich keinen Nutzen mehr, sondern verringert tatsächlich die Leistung, weil es in Ihrer Anwendung einige Engpässe gibt, die einfach nicht verschwinden. Sie möchten also auf keinen Fall nichtlinear sein.

Welche Anwendungen benötigen Skalierbarkeit?

Welche Anwendungen benötigen also Skalierbarkeit? Normalerweise handelt es sich dabei natürlich um Serveranwendungen. Webanwendungen, ASP.NET, jetzt ASP.NET Core Auch. Internetdienste. Auch hier können Sie dies entweder über WCF tun. Sie können dies über die ASP.NET-Web-API oder ASP tun.NET Core Web-API. Und das heißt, die Webdienste sind normalerweise das Backend für das Internet der Dinge, das heutzutage ein ziemlich schnell wachsender Bereich ist.

Dabei handelt es sich ebenfalls um Big-Data-Verarbeitungsanwendungen. Wenn Sie also viele Daten haben, kommt der Datenteil der Skalierbarkeit ins Spiel, aber auch hier geht es nicht um die Daten, sondern darum, wie schnell Sie sie verarbeiten können. Wenn Sie also über eine Big-Data-Verarbeitungsanwendung verfügen, muss diese skalierbar sein. Die meisten Big-Data-Verarbeitungsanwendungen sind im Allgemeinen nicht in .NET. Sie sind eher auf der Java-Seite und mein Fokus liegt mehr auf der .NET-Anwendung. Aber auch konzeptionell erfordern Big-Data-Verarbeitungsanwendungen Skalierbarkeit.

Und schließlich alle anderen Serveranwendungen. Sie können ein Finanzinstitut sein, Sie können eine große Bank sein, Sie haben Millionen von Kunden, sie rufen an, ändern ihre Adresse, stellen eine neue Karte aus oder was auch immer und Sie müssen sie bearbeiten, vielleicht möchten sie Geld überweisen, und Sie müssen alle diese Anfragen aus Compliance-Gründen innerhalb eines bestimmten Zeitrahmens bearbeiten. Es laufen also viele dieser Back-End-Batch-Prozesse, und sie müssen immer mehr Transaktionen innerhalb der sehr kurzen Zeitspanne verarbeiten, die gemessen an den wenigen Stunden, die Sie jede Nacht zur Verfügung haben, klein ist. Also jede Serveranwendung. Wenn Sie also über eine dieser Anwendungen verfügen und Skalierbarkeit benötigen, sind Sie hier genau richtig.

Das Skalierbarkeitsproblem

Was ist also das Skalierbarkeitsproblem? Nun, die Anwendungsebene ist nicht das Problem. In den meisten dieser Anwendungen, die ich erwähnt habe, scheint die Anwendungsebene einwandfrei zu funktionieren. Sie können weitere Server hinzufügen. Normalerweise verfügen Sie über eine Umgebung mit Lastenausgleich. Wenn Sie, sagen wir, eine ASP.NET-Anwendung haben, haben Sie oben einen Lastenausgleich und eine Gruppe von Servern, an die der Lastenausgleich den Datenverkehr sendet und je mehr Datenverkehr Sie benötigen, desto mehr Datenverkehr müssen Sie bewältigen Für mehr Benutzer fügen Sie einfach weitere Server hinzu. Es ist also ganz einfach.

Das Problem besteht jedoch darin, dass Ihre Datenbank unabhängig davon, ob es sich um relationale oder Mainframe-Daten handelt, zum Engpass wird. Und relational bedeutet nicht, dass es sich um eine bestimmte Datenbank handelt. Es könnte sich um einen SQL-Server handeln, es könnte Oracle, MySQL, Db2 oder irgendetwas davon sein. Alle relationalen Datenbanken haben die inhärente Schwäche, dass sie nicht skalierbar sind. Genau deshalb NoSQL Die Bewegung begann und tatsächlich haben wir sogar ein Produkt im .NET-Bereich namens NosDB Das ist eine Open Source NoSQL database aber die NoSQL databases sind nicht immer die Antwort. Ich meine, sie lösen definitiv das Skalierbarkeitsproblem. Technisch gesehen, wenn Sie a verwenden NoSQL database Sie werden keine Engpässe bei der Skalierbarkeit haben. Das Problem besteht jedoch darin, dass Sie aus einer Kombination aus technischen und geschäftlichen Gründen nicht alle Ihre Daten aus dem relationalen oder dem alten Mainframe verschieben können NoSQL.

So, das NoSQL ist eher etwas von dem, was wir die neuen Daten nennen, wissen Sie. Die traditionellen Geschäftsdaten befinden sich aus verschiedenen Gründen immer noch in relationalen Datenbanken. Das bedeutet also, dass Sie dieses Problem lösen müssen, während Sie mit relationalen Datenbanken arbeiten. Man kann nicht sagen, dass ich die relationale Datenbank einfach aus meinem Bild entfernen werde. Tatsächlich zieht nicht einmal einer unserer Kunden komplett in ein NoSQL. Sie verschieben einen Teil der Daten hinein NoSQL. Sogar größere Player wie MongoDB haben die gleiche Geschichte wie die Leute, zu denen sie wechseln NoSQL database Verschieben Sie einige der Daten nach NoSQL und sie behalten weiterhin die traditionellen Daten in der relationalen Datenbank.

Verteilte Cache-Bereitstellung (NCache)

Sie müssen also das Problem mit relationalen Datenbanken im Bild lösen, und hier kommt a verteilter Cache kommt ins Spiel. Es bringt Ihnen tatsächlich oft den gleichen Vorteil NoSQL database. Es ist tatsächlich, wenn man darüber nachdenkt, es ist ein NoSQL In-Memory-Schlüsselwertspeicher. Also, wissen Sie, wenn Sie es sich angesehen haben NoSQL databases, es gibt die JSON-Dokumentendatenbank, es gibt den Schlüsselwertspeicher und es gibt die Diagrammdatenbank und es gibt die anderen Typen. Also, der Schlüsselwertspeicher, wenn es sich um einen ... handelt. Das Einzige, was ein Distribute-Cache ausmacht, ist, dass er keine Persistenz durchführt, sondern alles im Speicher liegt. Es ist der Schlüsselwertspeicher. Und da es auf mehrere Server verteilt ist, bietet es Ihnen den gleichen Vorteil: Es ist skalierbar, da Sie weitere Server hinzufügen können. Betrachten Sie dies also als die Anwendungsebene hier oben. Hier ist die Anwendungsschicht und dann irgendwo oben ein Load Balancer. Und je mehr Server dieser Ebene hinzugefügt werden, desto mehr wird die Datenbank belastet, es sei denn, Sie fügen dazwischen eine Caching-Ebene ein.

Abbildung 1 - NCache Architektur

Die Caching-Ebene skaliert genauso wie die Anwendungsebene. Es gibt keine Engpässe, da Sie einfach immer mehr Kartons hinzufügen. Die Daten werden auf mehrere Server verteilt. Dies sind übrigens kostengünstige Server. Hierbei handelt es sich nicht um High-End-Datenbankserver. Tatsächlich unsere Kunden ... Die typische Konfiguration umfasst etwa 16 GB RAM, etwa 8 Kerne, wie eine typische Webserver-Box, aber nur mehr Speicher. 16 GB, 16 bis 32 GB, wir empfehlen nicht einmal mehr als 32 GB. Tatsächlich sind 64 GB so ziemlich das Maximum, das wir unseren Kunden empfehlen werden. Wir sagen: Fügen Sie weitere Server hinzu. Warum das? Denn wenn Sie den Speicher zu sehr vergrößern, gibt es in .NET eine sogenannte Garbage Collection. Und die Speicherbereinigung erfordert viel Rechenleistung. Je mehr Speicher Sie also haben, desto mehr Garbage Collection muss durchgeführt werden und desto schneller muss Ihre CPU werden. Dann gleicht Ihr Cache nicht immer mehr einer Datenbank und wird immer teurer und so weiter. Daher ist es besser, mehr Server zu haben, als ein paar High-End-Server.

Ein verteilter Cache bildet also im Wesentlichen einen Cluster von Servern. Dies ist normalerweise ein TCP-basierter Cluster. Dieser Cluster bedeutet, dass jeder Server im Cluster voneinander weiß und die Ressourcen in einer logischen Kapazität zusammenfasst. Wenn Sie über einen Cluster verfügen, müssen Sie dem Cluster einfach einen weiteren Server hinzufügen, wenn Sie die Kapazität erhöhen müssen. Oder Sie verzichten auf einen Server, wenn Sie die Kapazität verringern müssen. Und wenn Sie über diese Caching-Ebene verfügen, handelt es sich um einen In-Memory-Speicher, da Sie keine Daten dauerhaft speichern müssen. Es handelt sich nicht um einen dauerhaften Laden. Der permanente Speicher ist immer noch die Datenbank und da es sich um einen In-Memory-Speicher handelt, muss er auch die Datenreplikation ermöglichen.

Das Ziel in diesem Gesamtbild besteht darin, im Wesentlichen in etwa 80 % der Zeit auf den Cache zuzugreifen. Wenn Sie sich also vorstellen können, dass Ihre Datenbank völlig stressfrei wäre, wenn Sie 80 % der Zeit auf den Cache zugreifen würden, wissen Sie das. Man könnte die Skalierbarkeit wirklich deutlich steigern.

Frage: Muss die Anwendung immer noch nicht zu viel mit der Datenbank kommunizieren?

Eigentlich nicht. Es kommt also auf die Daten an. Die meisten Anwendungsdaten fallen jedoch in die Kategorie der Referenzdaten oder der Transaktionsdaten, die sich nicht alle paar Sekunden ändern. Es ändert sich vielleicht alle paar Minuten. Für all diese Daten führen Sie also viel mehr Lese- als Schreibvorgänge durch. Der erste Lesevorgang geht also in die Datenbank und auch dort gibt es Funktionen wie NCache verfügt über eine Funktion, mit der Sie den Cache mit Daten vorladen können. Sie können also den Cache mit allen Daten aufwärmen, von denen Sie glauben, dass Sie sie haben werden, und selbst wenn der Datenverkehr nicht betroffen ist, wird die Datenbank nicht beeinträchtigt. Aber es kommt auf die Daten an. Wenn Sie beispielsweise über andere Datentypen verfügen, beispielsweise wenn Sie Sitzungen darin speichern, gibt es für jeden Lesevorgang einen Schreibvorgang. Es kommt also darauf an und ich werde diese Details noch einmal durchgehen, aber das ist eine gute Frage.

Der Grund dafür wäre, dass der Cache die Daten lädt und im Cache speichert. Daher ist der Datenverkehr zwischen dem Cache und der Datenbank sehr selten. Wie gesagt, in 80 % der Fälle sind die Lesevorgänge abgeschlossen und der Cache enthält die Daten. Wenn Sie es also zwischenspeichern, speichern Sie es für eine bestimmte Zeit, und für diese Dauer wird der Cache nicht jedes Mal in die Datenbank verschoben. Die Anwendung kommt jedoch jedes Mal in den Cache. Obwohl also viel Datenverkehr herrscht, landet alles im Cache und plötzlich ist die Datenbank sehr klein.

Tatsächlich gibt es eine Partitionierung für jede Box, in der unterschiedliche Daten gespeichert werden, und es ist auch eine gewisse Redundanz eingebaut, um die Zuverlässigkeit zu gewährleisten, aber ich werde darauf detaillierter eingehen.

Dieses Bild (Abb. 1) soll Sie also irgendwie davon überzeugen, dass in der heutigen Umgebung mit hoher Skalierbarkeit verteilter Cache so etwas wie die de-facto-Best-Practice ist. Denken Sie also beim Entwerfen Ihrer Anwendung an einen Cache. Es spielt keine Rolle, welcher Cache. Das ist eine separate Diskussion. Die erste Diskussion besteht darin, dass Sie die Anwendung so entwerfen müssen, dass sie zu einem verteilten Cache führt. Wenn Sie dies tun, können Sie sicher sein, dass die Anwendung nicht ins Stocken gerät, wenn das Unternehmen die Leistung Ihrer Anwendung benötigt.

Und wenn Sie es nicht im Voraus planen, besteht der wirkliche Nachteil einer fehlenden Skalierungsmöglichkeit darin, dass dieses Problem dann auftritt, wenn das Unternehmen wirklich gut läuft. Stellen Sie sich vor, Sie sind eine Fluggesellschaft und haben gerade an diesem Wochenende eine Werbeaktion für einen Urlaubsort durchgeführt, und Millionen neuer Benutzer besuchen eine Website, um nach Flügen zu suchen und möglicherweise Tickets zu kaufen. Wenn die Leistung Ihrer Website mit jedem Klick um eine Minute nachlässt, verlieren Sie Kunden. Und wenn es noch schlimmer wird und Ihre Anwendung abstürzt, weil die Datenbank gerade überlastet ist, verlieren Sie viel Geschäft. Sie müssen also im Voraus planen. Auch wenn Sie heute nicht vor diesem Problem stehen und es hier wiederum nicht um Leistung geht.

Viele Leute denken, dass Cache verwendet werden sollte, weil dadurch die Leistung verbessert wird. Es verbessert zwar die Leistung, aber Datenbanken sind heutzutage ziemlich schnell. Wenn Sie nur diese fünf Benutzer haben. Ich habe noch nie gehört, dass sich jemand darüber beschwert hat, dass die Datenbank langsam ist. Das Problem ist also nicht die Leistung. Das Problem ist die Skalierbarkeit, denn es gibt nur einen Datenbankserver und Sie können weitere Server in der Anwendungsschicht hinzufügen, und dann wird die Datenbank plötzlich zum Engpass.

Frage: Sollten wir VMs oder physische Boxen für Cache-Cluster verwenden?

Sehr gute Frage. Ich wollte darüber reden und habe es vergessen, und es ist gut, dass Sie fragen. Es könnte sich also um physische Boxen handeln. Wir haben immer noch Kunden, die über physische Boxen verfügen, aber immer mehr unserer Kunden wechseln zu VMs, und jetzt geht der neue Trend zu Containern. Sie verfügen also mindestens über VMs. Jeder Cache-Server ist also eine VM. Sie verfügen also über mindestens zwei Cache-Server-VMs. Wie gesagt jeweils 16 bis 32 Gigs. Natürlich möchten Sie nicht beide VMS auf derselben physischen Box haben. Denn dann verlieren Sie den Vorteil der hohen Verfügbarkeit. Denn wenn diese Box abstürzt, sind beide VMS weg.

Noch eine Frage. Die physischen Daten werden also im Speicher gespeichert?

In Erinnerung. Genau genau. Es ist alles In-Memory-Speicher. Und da es sich um einen vorübergehenden Speicher handelt, speichern Sie ihn für ein paar Minuten, ein paar Stunden, ein paar Tage, ein paar Wochen, wissen Sie, Sie speichern ihn nicht dauerhaft. Der permanente Speicher ist immer noch die Datenbank. Was auch immer das ist. Das könnte, wie gesagt, ein Legacy-Mainframe sein, es könnte relational sein, es könnte sein NoSQL.

Sogar mit NoSQL database, sollten Sie einen verteilten Cache verwenden. Weil NoSQL ist nicht so schnell wie ein verteilter Cache und weil wir beide Produkte haben, die wir kennen. Wir machen die Benchmarks. Es ist immer noch zehnmal schneller.

Ich bin nicht vertraut mit NoSQL database, also habe ich mich nur gefragt, warum es eine bessere Leistung als eine relationale Datenbank bietet.

Es lässt sich besser skalieren, da es auch auf mehrere Server verteilt. So wie ein verteilter Cache 5, 10, 15, 20 Server haben kann, können Sie dasselbe mit einem tun NoSQL database. Sie können nicht 20 Server für SQL haben. Sie können vielleicht 2 haben, für Aktiv-Passiv oder Aktiv-Aktiv, aber das ist auch schon alles. Wissen Sie, man kann nicht wirklich skalieren. Aus Gründen der Skalierbarkeit.

Es sind also entweder VMs oder jetzt werden Container für die Verwaltung immer beliebter, und dies kann entweder lokal oder in der Cloud, in jeder Umgebung, erfolgen.

Allgemeine Verwendung von verteiltem Cache

Ich hoffe also, dass dieses Bild (Abbildung 1) Sie einigermaßen davon überzeugt, dass Sie Caching verwenden müssen. So, jetzt sind Sie überzeugt, sagen wir mal. Die nächste Frage ist: Wie verwende ich es? Wo verwende ich es, wissen Sie? Es gibt also drei häufige Orte, an denen Sie Caching verwenden.

App-Daten-Caching

Nummer eins ist das, worüber ich bisher gesprochen habe, nämlich die Anwendungsdaten, die genau dieses Bild darstellten. Hier werden Daten zwischengespeichert, sodass Sie nicht in die Datenbank gehen müssen. Das Einzige, was man beachten sollte Anwendungsdaten zwischenspeichern ist, dass die Daten jetzt an zwei Orten vorhanden sind. Einer ist der Cache, einer ist die Datenbank. Was könnte falsch sein, wenn Daten an zwei Orten vorhanden sind? Synchronisation. Das ist also ein so großes Problem, dass die meisten Leute Angst haben, den Cache für andere als schreibgeschützte Daten zu verwenden. Wenn Sie eine durchschnittliche Person fragen: Haben Sie darüber nachgedacht, den Cache zu verwenden, oder führen Sie Caching durch? Manchmal erstellen die Leute diese oder einige Hash-Tabellen im Speicher und legen nur schreibgeschützte Daten ab. Daten, die sich während der gesamten Anwendung oder in einem wirklich sehr komfortablen Zeitrahmen nie ändern. Nun, die schreibgeschützten Daten oder Referenzdaten machen nur 10–15 % der Gesamtdaten aus. Es bietet Ihnen also sicherlich viele Vorteile, aber der eigentliche Vorteil besteht darin, dass Sie alle Daten zwischenspeichern können. Das bedeutet, dass Sie wirklich in der Lage sein müssen, damit umzugehen …

Ein guter verteilter Cache muss die Synchronisierung bewältigen. Daher muss sichergestellt werden, dass der Cache immer aktuell ist. Damit Sie dem Cache vertrauen können, dass alles, was Sie aus dem Cache lesen, die neueste Kopie dieser Daten ist.

Und wenn Sie nicht über dieses Vertrauen verfügen, sind Sie auf schreibgeschützte Daten beschränkt, was den Wert des Caches praktisch minimiert oder verringert.

ASP.NET-spezifisches Caching

Der zweite Vorteil ist also der ASP.NET-spezifisches Caching. Ich gehe nicht auf ASP ein.NET Core aber ich werde kurz darauf eingehen. Aber beim ASP.NET-Caching gibt es drei Stellen, an denen Sie dies tun, und mindestens zwei. Wenn Sie über das MVC-Framework verfügen, verfügen Sie nicht über den Ansichtsstatus, aber die Sitzungen jeder ASP.NET-Anwendung haben Sitzungen und die Sitzungen müssen irgendwo gespeichert werden. Standardmäßig werden sie entweder im Arbeitsspeicher (In-Proc) gespeichert, also innerhalb des Arbeitsprozesses der ASP.NET-Anwendung oder des SQL-Servers. Der State-Server ist nicht in der Cloud verfügbar, sondern nur vor Ort und alle haben Probleme. Einige haben Skalierbarkeitsprobleme. Eigentlich haben alle Skalierbarkeitsprobleme. Einige haben auch Leistungsprobleme. Wie bei der SQL-Datenbank gibt es auch Leistungsprobleme.

Ein sehr guter Anwendungsfall für verteilten Cache besteht also darin, diese Sitzungen einfach in den Cache zu legen. Sie wissen, diese Sitzungen werden gespeichert … wenn Sie sie in SQL speichern, werden sie als Blobs gespeichert. Und relationale Datenbanken sind nicht für die Blob-Speicherung konzipiert. Aber, NoSQL oder Schlüsselwertspeicher, der Wert ist der Blob. Es passt also wirklich sehr gut in einen verteilten Cache. Natürlich müssen Sie auch eine Lösung finden … Immer mehr Menschen nutzen mehrere Datenbanken oder mehrere Rechenzentren, entweder für die Notfallwiederherstellung oder für den Lastausgleich bzw. für den geografischen Lastausgleich. Sie müssen also auch dieses Problem lösen.

Ein Ansichtsstatus ist etwas, das in ASP.NET nicht mehr vorhanden ist, aber wenn Sie vorher sind – ich denke ASP.NET 5. Wenn Sie ASP.NET 4 verwenden, dann Ansichtsstatus oder vor MVC, Ansichtsstatus existierte. In den meisten ASP.NET-Anwendungen, die damals entwickelt wurden, ist es immer noch vorhanden.

Für diejenigen unter Ihnen, die nicht wissen, was ein Ansichtsstatus ist: Ein Ansichtsstatus ist eine verschlüsselte Zeichenfolge, die vom Webserver an den Browser gesendet wird, nur um zurückzukommen, wenn ein Postback erfolgt. Diese Zeichenfolge könnte also Hunderte von Kilobyte groß sein und wird zum Browser übertragen, dort gespeichert und kommt dann zurück. Multiplizieren Sie das mit Millionen von Transaktionen, die Ihre Anwendung verarbeiten muss, und es treten zwei Probleme auf: Zum einen verbraucht es viel Bandbreite, was keine billige Bandbreite ist, und Sie müssen für die Bandbreite bezahlen. Zweitens verlangsamt es die Reaktionszeit, da es sich um eine schwere Nutzlast handelt, die transportiert wird. Es ist also ein idealer Fall, dies auf dem Server zwischenzuspeichern und einfach einen kleinen Schlüssel zu senden. Wenn er das nächste Mal zurückkommt, wird der Ansichtsstatus aus dem Cache abgerufen und auf der Seite bereitgestellt. Auch hier ist der Ansichtsstatus nur dann von Bedeutung, wenn Sie kein MVC-Framework verwenden, und in ASP ist er definitiv nicht einmal vorhanden.NET Core weil ASP.NET Core ist MVC.

Der ASP.NET-Ausgabecache ist ebenfalls Teil des ASP.NET framework, nicht im ASP.NET Core wo es so ziemlich die Seitenausgaben zwischenspeichert. Wenn sich Ihre Seite also bei der nächsten Anfrage nicht ändert, warum sollten Sie sie dann erneut ausführen? Also speichert ASP.NET die Seite im Cache, sodass beim nächsten Mal, wenn die Anfrage mit den gleichen Parametern und allem gleich kommt, eine Ausgabe der letzten Ausführung an die Seite geliefert wird.

Dieses Framework ist also bereits vorhanden und es ist wirklich eine gute Sache, einen verteilten Cache dafür zu verwenden, sodass es in einer Umgebung mit mehreren Servern, sobald es zwischengespeichert ist, sofort für alle Server verfügbar ist. ASP.NET Core verfügt nur über Sitzungen zum Zwischenspeichern und es gibt keinen Ansichtsstatus und keinen Ausgabecache. Aber es gibt noch eine andere Sache, die sogenannte Antwort-Caching. Also, ASP.NET Core hat sich mittlerweile mit den gesamten Webanwendungen vereinheitlicht, bei denen die Inhaltszwischenspeicherung außerhalb des Servers erfolgt. Das ist also auch ein guter Kandidat für das Caching. Also, ASP.NET Core hat dies ein Middleware-Konzept für das Antwort-Caching. Es gibt also eine integrierte Middleware, die Sie verwenden können, und dann können Sie eine Middleware eines Drittanbieters verwenden. Wie NCache werde demnächst eins zur Verfügung stellen.

Was das ASP.NET-Caching angeht, ist es wichtig, jetzt im Hinterkopf zu behalten, dass Sie diese Daten nicht mehr im Cache speichern. Im Gegensatz zu den Anwendungsdaten, bei denen die Daten an zwei Orten vorhanden sind, existieren die Daten jetzt nur noch an einem Ort, und zwar im Cache, einem In-Memory-Cache. Was kann also schiefgehen, wenn der In-Memory-Store Ihr einziger Store ist? Ja. Ich meine, wenn die Kiste kaputt geht, bist du vollgespritzt. Denn das Gedächtnis ist flüchtig. Es bleibt nicht bestehen. Der Weg, damit umzugehen, besteht natürlich darin, eine Replikation durchzuführen. Diese Daten auf mehr als einem Server zu haben. Aber auch hier sind zwei sehr unterschiedliche Probleme zu lösen. Ein guter verteilter Cache muss eine intelligente Replikation durchführen. Wenn Sie beispielsweise ASP.NET-Sitzungen sicher speichern möchten. Was passiert sonst? Kommen wir zurück zur Fluggesellschaft. Ich bin gerade auf diese Website gegangen. Ich werde Tickets im Wert von 5,000 $ kaufen. Ich habe meine ganze Flugsuche durchgeführt, alle möglichen Kombinationen, und ich bin dabei, ... Ich habe meine Zahlungsinformationen eingegeben und war dabei, sie abzusenden, und plötzlich bin ich wieder auf der Startseite zurückgekehrt, was auch immer, denn meine Sitzung ist verloren. Denn als ich auf „Senden“ klickte, ging es zum Webserver, dieser Webserver war nicht da, er stürzte ab und die Sitzung war weg. Also definitiv kein gutes Bild.

Gemeinsame Nutzung von Laufzeitdaten durch Ereignisse

Der dritte Anwendungsfall ist ein gemeinsame Nutzung von Laufzeitdaten durch Ereignisse. Dies ist etwas, was viele Leute nicht wissen. Es wird immer beliebter, dass ein verteilter Cache, sobald Sie ihn in Ihrer Umgebung haben, eine wirklich leistungsstarke Plattform für den Datenaustausch zwischen mehreren Anwendungen ist, z Pub / Sub Modell- oder andere ereignisgesteuerte Datenfreigabe.

Beispielsweise verfügen Sie möglicherweise über mehrere Anwendungen, die Daten gemeinsam nutzen müssen. Eine Anwendung produziert etwas, legt es im Cache ab, löst einige Ereignisse aus, es gibt Abonnenten für dieses Ereignis. Es gibt also andere Anwendungsinstanzen oder andere Anwendungen, und oft findet in Anwendungen eine Art Workflow statt. Dass zuerst etwas getan wird und dann darauf basierend etwas anderes getan wird. Und in diesem Fall gibt es diese Abonnenten dieser Veranstaltungen. Diese Anträge werden benachrichtigt.

Denken Sie jetzt an dieses Bild (Figure 1) Hier. Betrachten Sie dies nicht als einen Cache zwischen der Anwendung und der Datenbank. Stellen Sie sich das wie einen Nachrichtenbus vor, und diese Anwendungen sind alle mit dem Nachrichtenbus verbunden. Eine Anwendung von diesem Server legt Daten im Cache ab und löst ein Ereignis aus. Möglicherweise werden andere Anwendungen auf einigen dieser Server benachrichtigt und greifen sofort auf die Daten zu. Sehr kraftvolle Art und Weise.

Manche Leute verwenden Nachrichtenwarteschlangen. Für viele dieser Nachrichtenwarteschlangen haben sie einen bestimmten Zweck. Ein verteilter Cache ist nicht dazu da, sie vollständig zu ersetzen, sondern nur eine Teilmenge der Fälle. Wenn die gesamte Datenfreigabe innerhalb desselben Rechenzentrums erfolgt, handelt es sich nicht um eine sehr verteilte Umgebung und es handelt sich um eine Umgebung mit hohem Datenverkehr. Im Gegensatz zu einem verteilten Cache ist eine Nachrichtenwarteschlange nicht skalierbar. Denn eine Nachrichtenwarteschlange hat keinen solchen Cluster. Mehr kann man eigentlich nicht hinzufügen. Wenn also Millionen von Transaktionen stattfinden und ein Teil davon auch Nachrichteninformationen sind, können Nachrichtenwarteschlangen diese Last nicht bewältigen, ein Cache jedoch schon.

Die gemeinsame Nutzung von Laufzeitdaten ist also eine wirklich leistungsstarke Möglichkeit, und ich werde darauf eingehen. Auch hier sind die Daten bei der gemeinsamen Nutzung von Laufzeitdaten normalerweise nur im Cache vorhanden. Allerdings könnte eine andere Form davon in der Datenbank vorhanden sein. Denn es wurde aus der Datenbank gelesen, in eine andere Form umgewandelt und dann zur gemeinsamen Nutzung im Cache abgelegt.

Daher sind einige der Funktionen in allen Caches gleich. Einige sind nur NCache auf der .NET-Seite aber alles, was ist NCache auf der .NET-Seite ist keine proprietäre .NET-Funktion. Denn auf der Java-Seite und in allen Java-Caches sehen Sie dieselben Funktionen. Daher ist Java ein wesentlich fortschrittlicherer oder ausgereifterer Markt, da Java schon länger als .NET die serverseitige Technologie ist. Sie sehen also ... Auf der Java-Seite. Auf der .NET-Seite wird es in einigen Caches angezeigt, nicht in allen. Zum Beispiel, AppFabricIch glaube, ich hatte es nicht. Redis hat einiges davon, nicht alles. NCache verfügt über einen vollständigen Cache wie die Java-Caches.

Das sind also die drei Anwendungsfälle. Haben Sie Fragen dazu, bevor ich näher auf die einzelnen Themen eintauche?

Hands-on-Demo

Bevor ich darauf eingehe, möchte ich Ihnen zunächst zeigen, wie ein Cache aussieht. Ich werde es natürlich nutzen NCache als Beispiel, aber der Zweck besteht darin, Ihnen ein Gefühl dafür zu vermitteln, wie ein Cache wirklich aussieht. Ich habe beispielsweise drei VMs in Azure. Sie rennen. Demo1 und Demo2 sind meine Cache-Server-VMs. Ich werde also einen 2-Knoten-Cache-Cluster haben.

Demo-Client

Der Demo-Client ist mein Anwendungsserver. Es handelt sich also um eine Cache-Client-VM.

Erstellen Sie einen geclusterten Cache

Ich bin hier bei der Demo-Client-VM angemeldet. Ich werde fortfahren und einen Cluster-Cache erstellen. Im Falle von NCacheIch werde dieses Tool namens verwenden NCache Geschäftsführer, ein grafisches Werkzeug. Ich werde hierher kommen und sagen: Lassen Sie mich zunächst sicherstellen, dass der Cache nicht bereits vorhanden ist. Okay, das ist nicht der Fall. Okay, ich werde hierher kommen und sagen: Erstellen Sie einen neuen Cluster-Cache.

Im Falle von NCache Alle Caches sind benannt. Mein Cache heißt also DemoCache. Ich belasse einfach alle Standardeinstellungen. Ich werde nicht näher darauf eingehen. Ich behalte einfach … Ich werde nur über die wichtigen Teile sprechen.

Das erste, was Sie auswählen, ist das, was wir a nennen Caching-Topologie in NCache Und hier hat einer von Ihnen die Frage zur Partitionierung gestellt. Sind die Daten wirklich verteilt oder sind auf jedem Server die gleichen Daten vorhanden? Eine Partitionsreplik ist also eine Topologie, die NCache gibt Ihnen.

Ich werde zum Beispiel schnell darauf eingehen und schnell darüber sprechen, was diese Topologie ist? Also eine Partitionsreplikat-Topologie … Das ist also eine partitionierte Topologie, das ist eine Partitionsreplik.

Bei einer Partitionierung verfügt jeder Server über ein Zehntel der Daten. Also, wenn ja, sagen wir mal, im Falle von NCacheWenn Sie einen Cluster-Cache erstellen, werden eintausend Buckets erstellt. Wenn Sie also einen Cluster mit zwei Servern haben, beträgt jeder Server 500. Wenn Sie drei haben, ist jeder Server ein Dritteltausend.

Diese Buckets ähneln also im Wesentlichen den Hash-Tabellen-Buckets. Jedem Bucket ist ein Schlüsselwertbereich zugeordnet. Es gibt also eine Hash-Map-Funktion, die Ihre Schlüssel in Hash-Werte umwandelt und sie basierend auf den Schlüsseln in die Buckets fallen lassen, in die sie fallen sollen. Ein partitioniertes Replikat verfügt also über eine Partition auf jedem Server. Nehmen wir an, wenn Sie hierher kommen würden. Nehmen wir an, hier handelt es sich um einen Cluster mit drei Servern, also mit drei Partitionen, und jede Partition verfügt über ein Backup oder eine Replik auf einem anderen Server.

Im Falle von NCache Das Replikat ist nicht aktiv. Es ist passiv. Es kommuniziert also nur die Partition mit den Replikaten. Die Anwendung kommuniziert mit den Partitionen. Nehmen wir an, jeder Cache-Client, jeder Anwendungsserver stellt eine Verbindung zu allen Cache-Servern her. Es stellt eine Verbindung her und ruft alle Informationen zur Clustermitgliedschaft ab. Die Verbreitungskarte ist diese Bucket-Map. Es erhält also die Bucket-Map, die ihm sagt, wo sich jeder Bucket befindet? Basierend darauf weiß es, okay, wenn ich Element Nummer drei hinzufügen muss, muss ich zu Server 2 gehen. Denn dort befindet sich Partition 2, die den Schlüssel für Element Nummer 3 haben soll. Es geht also direkt zu diesem Server und kann das tun.

Und wenn dann ein Server ausfällt, fällt beispielsweise Partition 3 aus, sodass Replikat 3 sofort aktiv wird. Es wird also jetzt eine Partition. Es wird von einer Replik in eine Partition umgewandelt. Denn Sie wissen es nicht, Sie wollen weitermachen. Der Cache muss laufen, die Anwendung muss weiterlaufen. Es ist eine hohe Verfügbarkeit, richtig. Und dann erkennt diese Partition drei, dass es nur zwei Server gibt, also muss sie sich in diesen beiden Partitionen zusammenführen und sozusagen verschwinden, verschwinden. Es führt also die beiden anderen Partitionen zusammen und sobald dies erledigt ist, wird hier ein Replikat für Partition zwei erstellt.

Um Ihnen noch einmal einen Überblick darüber zu geben, was diese Topologie bedeutet. Auf diese Weise erfolgt die Verteilung, um sicherzustellen, dass Sie immer mehr Speicher haben, wenn Sie weitere Server hinzufügen. Auf diese Weise erfolgt auch die Replikation, sodass alle Daten auf zwei Servern vorhanden sind. Es gibt also keinen Datenverlust, wenn ein Server ausfällt.

Auch hier besagt die Theorie der Hochverfügbarkeit, dass zwei Server nicht gleichzeitig ausfallen. Die Wahrscheinlichkeit, dass zwei Server gleichzeitig ausfallen, ist im Vergleich zum Ausfall eines einzelnen Servers astronomisch gering. Natürlich, wie gesagt, wenn zwei Server an die gleiche Stromversorgung angeschlossen sind und die Stromversorgung ausfällt, gehe ich davon aus, dass alles redundant ist. Dann scheitern nicht zwei Dinge gleichzeitig. Deshalb ist es mehr als genug, nur zwei Exemplare zu haben.

Lass uns zurück gehen. Das war also die Partitionsreplik. Dann werde ich eine asynchrone Replikation auswählen.

Es gibt also zwei Modi. Die meisten verteilten Caches führen diese sogenannte Eventualkonsistenz durch. Das bedeutet, dass aufgrund der Verteilung alles langsamer wird, wenn Sie eine sofortige Synchronisierung durchführen müssten. Aber die meisten Daten, die Sie sich leisten können, werden in eine Warteschlange gestellt und asynchron aktualisiert. Daher wird hier standardmäßig die Asynchronität verwendet.

Ich wähle den Demo-Client oder Demo 1 ist der erste Server. Ich werde Demo 2 als zweiten Server auswählen.

Ich komme hierher und übernehme einfach die Standardeinstellungen.

Ich werde angeben, wie viel Speicher jeder Server verwenden soll.

Natürlich wird es in Ihrem Fall noch viel mehr sein. Nehmen wir also an, wenn Sie 16 GB Speicher in jeder Box haben, müssen Sie einen Teil für die Partition und einen Teil für die Replik zuweisen. Nehmen wir also an, es sollten 2 bis 3 GB für das Betriebssystem und andere Prozesse übrig bleiben und es bleiben etwa 13 GB übrig. Also, um 7.5 oder 6.5 GB, einer für die Partition, einer für die Replik. Und weil Sie diese Größe angeben, um sicherzustellen, dass der Cache nicht mehr verbraucht. Da es sich um einen In-Memory-Speicher handelt, ist der Speicher immer begrenzt und auf dieser Box können möglicherweise andere Anwendungen ausgeführt werden. Sie möchten also gewissermaßen begrenzen, wie viel Speicher der Cache verwenden soll, und sobald der Cache diesen Speicher verwendet hat ...

Dann wäre also die nächste Seite. Nehmen wir an, Sie haben den gesamten Speicher aufgebraucht. Nun ist der Cache voll. Es können also nur zwei Dinge passieren. Erstens werden entweder einige der älteren oder anderen Daten entfernt oder zweitens werden die neuen Einfügungen abgelehnt. Sie müssen also diese beiden auswählen. Natürlich möchten Sie Ihre Kapazitätsplanung so durchführen, dass die Daten, d. h. Anwendungsdaten, entfernt werden können, da Sie sie jederzeit aus der Datenbank neu laden können. Es ist nicht in Ordnung, Sitzungen zu räumen. Daher möchten Sie Ihre Kapazitätsplanung so durchführen, dass diese Sitzungen niemals geräumt werden. Jetzt verfügen Sie über genügend Arbeitsspeicher, genügend RAM und genügend Server, sodass Sie immer über Speicher für Sitzungen verfügen. Und Sie möchten die Sitzungen ablaufen lassen, nicht das Thema entfernen. Räumung bedeutet, dass die Sitzungen noch nicht abgelaufen sind, aber kein Speicher mehr vorhanden ist. Sie führen also eine Zwangsräumung durch. Ablauf im Falle von NCache bedeutet, dass Sie angegeben haben, dass eine Sitzung beispielsweise nur für 20 Minuten Inaktivität gültig ist. Danach soll die Sitzung bereinigt werden. Das ist also Ablauf. Der Ablauf ist also in Ordnung, es gibt kein Problem, aber Sie sollten die Sitzung nicht entfernen, sondern die Anwendungsdaten.

Was tun Sie also im Falle eines Falles? NCacheerstellen Sie einen Cache für die Sitzungen und einen Cache für Anwendungsdaten. So trennt man die beiden. Nehmen wir an, ich habe gerade diesen Cache erstellt. Es handelt sich also um einen Cache mit zwei Knoten. Ich werde einen Client-Knoten hinzufügen, der meine Box, den Demo-Client, darstellt, und jetzt starte ich einfach den Cache.

Client-Knoten hinzufügen

Stress simulieren und Cache-Statistiken überwachen

Wie Sie sehen, ist es also ziemlich einfach. Es handelt sich um eine Art Benutzeroberfläche im Explorer-Stil. Von einem Ort aus können Sie einen Multi-Server-Cache erstellen, ihn verwalten, überwachen und dann, wenn Sie das getan haben, wird, sagen wir mal, jetzt, da es geschehen ist, einige PerfMon-Zähler angezeigt und ich werde dieses Tool namens Stresstest-Tool ausführen, das mitgeliefert wird NCache, mit dem Sie die Anwendungsnutzung sehr schnell simulieren können.

Stresstest-Tool

Nehmen wir an, ich habe das gerade getan und jetzt fängt es an ... Es werden also etwa 500 bis 800 Transaktionen pro Server durchgeführt. Also, das ist ungefähr mal 2, das ist die Last. Ich möchte die Belastung erhöhen. Deshalb möchte ich ein weiteres Stresstest-Tool hinzufügen. Unsere Kunden nutzen dies häufig, da fast jeder sehen möchte, wie der Cache in seiner Umgebung funktioniert. Wissen Sie, wir haben alle Benchmarks veröffentlicht und alles, aber sie wollen es in ihrer Umgebung sehen. Anstelle von Programmierung und Anwendung können sie dies also sehr schnell simulieren. Nehmen wir also an, ich habe zwei davon ausgeführt und jetzt ist die Last gestiegen. Ich kann also immer mehr davon hinzufügen, bis ich diese beiden Server voll ausgelastet habe. Hier kommt es also auf die Skalierbarkeit an.

Cache-Statistiken

Diese beiden Server arbeiten derzeit superschnell. Aber wenn ich die Last erhöhe, erreichen sie ab einem bestimmten Punkt ihr Maximum, was bei einer Datenbank der Fall ist. Der einzige Unterschied besteht darin, dass Sie hierher kommen und einen weiteren Knoten hinzufügen können. Wenn Sie also eine dritte VM hatten, kommen Sie einfach hierher und fügen das hier hinzu, und sobald Sie das tun, wird die Last plötzlich verteilt und wir haben dieses Bild, wo, wissen Sie, wo ich Ihnen gezeigt habe, wo Sie angefangen haben Wenn die beiden Server ausgelastet sind, möchten Sie einen dritten hinzufügen. Sie holen sich also einfach eine weitere VM und fügen sie hinzu, und schon wird daraus ein Drei-Server-System NCache wird automatisch alles neu anpassen, wir werden neu partitionieren bzw redisHommage an die Bucket Map. Daher wird zur Laufzeit ein dritter Server hinzugefügt. Plötzlich haben Sie dieses Kapazitätsproblem nicht mehr.

Cache-Statistiken

Ja, also was Sie tun, ist, das zu installieren NCache Serversoftware, auf allen diesen VMs. Im Falle einer Cloud verfügen Sie normalerweise über ein vorkonfiguriertes VM-Image, aus dem Sie die Instanzen erstellen, und starten einfach eine neue VM NCache Die Software wird ausgeführt und Sie fügen sie einfach diesem Cluster hinzu.

Aber auch hier ist der Hauptpunkt: Im Gegensatz zu einer Datenbank, in der Sie, sobald Sie den Maximalzustand erreicht haben, abgespritzt werden, wissen Sie. Wie geht's? Weißt du, okay, ich möchte ein teureres kaufen. Nun, dann muss man sich eine neue Kiste kaufen und diese Kiste zerstören, und das ist ein Albtraum. Hier fügen Sie einfach ein weiteres Feld hinzu.

Die richtigen NCache mit ASP.NET-Sitzungen

Deshalb werde ich mich jetzt als nächstes damit befassen. Jetzt wissen wir also, wie ein Cache aussieht. So, jetzt sehen wir das ... im Falle von NCache, alle Caches werden benannt. Solange Sie also den Namen des Caches kennen, stellen Sie einfach eine Verbindung zum Cache her. Wie stellen Sie also eine Verbindung zum Cache für Sitzungen her? Das ist am einfachsten. Auch hier ist es für die meisten unserer Kunden das Erste, was sie tun NCache Sie verwenden es für Sitzungen. Warum? Weil keine Programmierung erforderlich ist. Das Einzige, was Sie bei Sitzungen sicherstellen müssen, ist, dass alle Objekte, die Sie in die Sitzung einfügen, alle serialisierbar sind. Wenn Sie Sitzungen bereits in SQL speichern, haben Sie dies bereits sichergestellt. Wenn Sie Sitzungen im In-Proc-Modus speichern, haben Sie dies möglicherweise nicht sichergestellt. Das ist also der einzige Test, den Sie machen müssen. Aber danach ist es ziemlich einfach.

Ich zeige Ihnen hier nur eine kleine Kostprobe. So gibt es hier beispielsweise ein Beispiel mit dem Namen „Session Store Provider Sample“. Ich habe also eine ASP.NET-Anwendung. Ich gehe zur web.config. Gehen Sie davon aus, dass ich mich auf dieser Anwendungsserver-Box befinde. Wenn Sie das Bild hier sehen. Lassen Sie mich tatsächlich hierher zurückkehren. Hier ist also der Cache-Server, aber meine Anwendung läuft auf dieser Box. Also habe ich auf dieser Box zwei Servercluster erstellt und diesem einen Client hinzugefügt, richtig. Was nun also bei diesem Kunden passiert ist, ist, dass dies der Fall ist NCache, ups nein, nicht hier. Okay, für den Fall NCache Es erstellt tatsächlich im Konfigurationsordner eine client.ncconf, also erstellt es einen Eintrag. So weiß die Anwendung, mit welchem ​​Server sie sich verbinden muss.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <ncache-server connection-retries="3" retry-connection-delay="0" retry-interval="1" command-retries="3" command-retry-interval="0.1" client-request-timeout="90" connection-timeout="5" port="9800" local-server-ip="10.2.0.5" enable-keep-alive="False" keep-alive-interval="0"/>
    <cache id="demoCache" client-cache-id="clientCache" client-cache-syncmode="optimistic" skip-client-cache-if-unavailable="True" reconnect-client-cache-interval="10" default-readthru-provider="" default-writethru-provider="" load-balance="False" enable-client-logs="False" log-level="error">
      <server name="10.2.0.5"/>
      <server name="10.2.0.6"/>
    </cache>
  </configuration>

Auch hier handelt es sich nur um die anfängliche Serverliste. Es ist nicht die endgültige Liste. Warum? Denn was wäre, wenn Sie für eine Hochverfügbarkeitsumgebung diesen dritten Server zur Laufzeit hinzufügen würden? Das ist nicht in dieser Liste, oder? Nehmen wir also an, das war Punkt acht (0.8), so etwas. Dies ist also nur die erste Liste. Sobald die Anwendung einen von ihnen kennt, stellt sie eine Verbindung zu diesem her. Das erste, was mit der Anwendung passiert, ist, dass sie nach der Verbindung die Informationen zur Clustermitgliedschaft empfängt. Außerdem wird jedes Mal, wenn sich diese Clustermitgliedschaft ändert und Sie einen weiteren Server hinzufügen, eine aktualisierte Clustermitgliedschaft an den Client gesendet und alles im Speicher gespeichert. Es ist alles vor Ihrer Anwendung verborgen. Es wird alles von der verwaltet NCache Client-Teil, aber so weiß die Anwendung, wie sie eine Verbindung zu Ihrem Cache herstellen kann.

Also, im Falle von Sitzungen kommen Sie einfach hierher. In den Sitzungen müssen Sie also zunächst die Baugruppe hinzufügen.

...
<compilation defaultLanguage="c#" debug="true" targetFramework="4.0">
    <compilers>
		<compiler language="c#" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" extension=".cs" compilerOptions="/d:DEBUG;TRACE" />
	</compilers>
	<assemblies>
	<add assembly="Alachisoft.NCache.SessionStoreProvider, Version=4.6.0.0, Culture=neutral, PublicKeyToken=CFF5926ED6A53769" /></assemblies>
</compilation>
...

Im Falle von NCache Sie haben einfach ... diese Assembly implementiert das Sitzungsstatus-Provider-Schnittstelle das ist Teil des ASP.NET framework und indem du das tust NCache wird ein Dritter, ein benutzerdefinierter Speicher. Das ist also nur ein Kopieren und Einfügen und dann die tatsächlichen Änderungen im Sitzungsstatus-Tag. Wenn Sie hier also vorgehen, stellen Sie sicher, dass der Modus benutzerdefiniert ist.

...
<sessionState cookieless="false" regenerateExpiredSessionId="true" mode="Custom" customProvider="NCacheSessionProvider" timeout="20">
    <providers>
        <add name="NCacheSessionProvider" type="Alachisoft.NCache.Web.SessionState.NSessionStoreProvider" sessionAppId="WebF1" cacheName="democache" writeExceptionsToEventLog="false" enableLogs="false" />
    </providers>
</sessionState>
...

Die Modi sind also: Es gibt In-Proc, den Statusserver, SQL und es gibt den Benutzerdefiniert. Es gibt also vier Modi, die Sie haben. Wenn der Modus also benutzerdefiniert ist, möchten Sie auch sicherstellen, dass das Zeitlimit dem gewünschten Sitzungszeitlimit entspricht, und kopieren Sie dann die Anbieterdetails. Welches ist, im Fall von NCache Es ist diese Zeile und das einzige, was sie ändern müssen, ist der Cache-Name. So ist hier beispielsweise der Cache-Name bereits geändert. Du nimmst diese Änderung vor, das ist alles. Und sobald Sie diese Änderung vornehmen, startet ASP.NET Ihren Arbeitsprozess trotzdem neu und Sie werden sehen, dass jede Sitzung als ein Objekt im Cache gespeichert wird und Sie werden sofort eine enorme Leistungssteigerung feststellen. Denn jetzt speichern Sie sie nicht in SQL.

Also der schnellste Weg, von einem verteilten Cache zu profitieren NCache ist es einfach, es für Sitzungen einzusetzen. Denn für das Zwischenspeichern von Objekten für Anwendungsdaten gibt es mehr Arbeit. Natürlich wissen Sie, dass Sie das tun möchten, und darauf werde ich näher eingehen, aber der erste Anwendungsfall ist die ASP.NET-Spezifikation.

Haben Sie Fragen dazu? Wir haben beispielsweise gesehen, dass einige unserer High-End-Kunden etwa 50 bis 100 Server in der Anwendungsschicht haben. Nehmen wir an, ein Verhältnis von 1 zu 5 ist die übliche Vorgehensweise. Bei einer Konfiguration mit 100 Servern verfügen sie also über 20 Cache-Server. Mehr als 50, das sind sehr wenige, wissen Sie, man muss wirklich viel Datenverkehr haben, um mehr als 50 Server in einer Umgebung mit Lastausgleich zu haben. Die meisten Kunden verfügen über 4 bis 12 Server. Und wir empfehlen, wie gesagt, ein Verhältnis von 4 zu 1 oder 5 zu 1, je nachdem, um welche Art der Anwendung es sich handelt. Manchmal kann es sogar mehr als 5 zu 1 sein, aber ich meine, das ist der durchschnittliche Anwendungsfall. Wenn Sie also ein 5-zu-1-Verhältnis haben und 12 Server in der Anwendungsebene haben, haben Sie eine Caching-Ebene mit drei Servern. Also, nicht so viele Verbindungen, ja.

Theoretisch ja. Wenn Sie immer mehr Server hinzufügen, wird es viele Redundanzen geben. Aber die Anwendungsfälle, über die wir sprechen, fallen nicht darunter. Die Big-Data-Verarbeitung könnte 50 oder 100 Server umfassen, aber in diesem Fall gibt es keine Clients und bei der Big-Data-Verarbeitung sind es nur die Server. Denn alles läuft auf dem Server selbst. Aber im Falle einer Webanwendung oder Webdienstanwendung nennen wir das E-Commerce, das Online-Geschäftsmodell. Ich meine, das ist ziemlich viel. Ich denke, Sie können davon ausgehen, dass Sie in den meisten Fällen weniger als 20 Server haben und ein sehr kleiner Prozentsatz der Kunden mehr als 20 hat, und mehr als 50 ist sehr klein.

Ja, auf jeden Fall. Wenn ich also zum Beispiel hierher käme, würde ich einfach … wenn ich hierher käme. Ich verwende das nicht NuGet-Paket hier, aber ich könnte hierher kommen und zum NuGet gehen und ich könnte hier sagen NCache, zum Beispiel, und Sie erhalten eine NCache SDKs, NCache Session Services für Unternehmen und Profis, außerdem gibt es Open-Source und NHibernate. Es gibt also eine Menge NuGets. Also, ein typisches … für die Sitzungen fügen Sie einfach dieses Sitzungs-NuGet-Paket hinzu. Für das Zwischenspeichern der Anwendungsdaten fügen Sie einfach das SDK hinzu, das alles enthält, was Sie benötigen.

Cache-Statistiken

Übersicht über App-Daten-Caching (API)

Damit Anwendungsdaten-Caching ist etwas, wo man programmieren muss. Sie sehen den Cache also als Datenbank. Sie stellen eine Verbindung zum Cache her. Im Falle von NCache Wir haben diese Methode aufgerufen Cache initialisieren.

Cache-Verbindung
Cache cache = NCache.InitializeCache("myCache");
cache.Dispose();
Abrufen von Daten
Employee employee = (Employee) cache.Get("Employee:1000");
Employee employee = (Employee) cache["Employee:1000"];
bool isPresent = cache.Contains("Employee:1000");
Schreiben von Daten
cache.Add("Employee:1000", employee);
cache.AddAsync("Employee:1000", employee);

cache.Insert("Employee:1000", employee);
cache.InsertAsync("Employee:1000", employee);
cache["Employee:1000"] = employee;

Employee employee = (Employee) cache.Remove("Employee:1000");
cache.RemoveAsync("Employee:1000");

Möglicherweise haben Sie andere Methoden für andere Caches und für diesen Fall gibt es einen Cache-Namen NCache wie wir besprochen haben, und dies gibt Ihnen ein Cache-Handle.

Kommen wir also zu einer Anwendung. Wir gehen noch einmal darauf ein … Dies ist eine einfache Konsolenanwendung. Wenn Sie das NuGet-Paket hinzugefügt haben, wird dies alles für Sie erledigt. Sie würden auf einige verweisen NCache Versammlungen. Es gibt also nur zwei Assemblys, auf die Sie verweisen müssen: NCache.Laufzeit und NCache.Netz. NCache.Netz ist die tatsächliche öffentliche API im Fall von NCache. Anschließend fügen Sie in Ihre Anwendung den Namespace ein. Also, Sie haben das NCache.Laufzeit und NCache.Web.Caching als Namensräume.

Dann erhalten Sie zu Beginn der Anwendung den Cache-Namen beispielsweise aus der App.config, initialisieren den Cache und erhalten ein Cache-Handle. Hier ist also das Cache-Handle, das Sie überall in der Anwendung verwenden müssen.

Kommen wir nun zum Cache-Handle. Das können Sie also tun cache.Hinzufügen, Schlüssel angeben. Der Schlüssel ist, wie gesagt, normalerweise eine Zeichenfolge. Objekt ist Ihr tatsächliches Objekt, was auch immer das ist. Es ist ein beliebiges .NET-Objekt, NCache wird es tatsächlich serialisieren und an den Cluster senden. All dies geschieht also auf der Clientseite, auf dem Anwendungsserver.

// Alachisoft (R) NCache Sample Code.
using Alachisoft.NCache.Runtime;
using Alachisoft.NCache.Sample.Data;
using Alachisoft.NCache.Web.Caching;
using System;
using System.Configuration;

namespace Alachisoft.NCache.Samples
{
    /// <summary>
    /// Class that provides the functionality of the sample
    /// </summary>
    public class BasicOperations
    {
        private static ICache _cache;

        /// <summary>
        /// Executing this method will perform all the operations of the sample
        /// </summary>
        public static void Run()
        {
            // Initialize cache
            InitializeCache();

            // Create a simple customer object
            Customer customer = CreateNewCustomer();
            string key = GetKey(customer);

            // Adding item synchronously
            AddObjectToCache(key, customer);

            // Get the object from cache
            customer = GetObjectFromCache(key);

            // Modify the object and update in cache
            UpdateObjectInCache(key, customer);

            // Remove the existing object from cache
            RemoveObjectFromCache(key);

            // Dispose the cache once done
            _cache.Dispose();
        }

        /// <summary>
        /// This method initializes the cache
        /// </summary>
        private static void InitializeCache()
        {
            string cache = ConfigurationManager.AppSettings["CacheID"];

            if (String.IsNullOrEmpty(cache))
            {
                Console.WriteLine("The CacheID cannot be null or empty.");
                return;
            }

            // Initialize an instance of the cache to begin performing operations:
            _cache = NCache.Web.Caching.NCache.InitializeCache(cache);

            // Print output on console
            Console.WriteLine(string.Format("\nCache '{0}' is initialized.", cache));
        }

        /// <summary>
        /// This method adds object in the cache using synchronous api
        /// </summary>
        /// <param name="key"> String key to be added in cache </param>
        /// <param name="customer"> Instance of Customer that will be added to cache </param>
        private static void AddObjectToCache(string key, Customer customer)
        {
            TimeSpan expirationInterval = new TimeSpan(0, 1, 0);

            Expiration expiration = new Expiration(ExpirationType.Absolute);
            expiration.ExpireAfter = expirationInterval;

            //Populating cache item
            CacheItem item = new CacheItem(customer);
            item.Expiration = expiration;

            // Adding cacheitem to cache with an absolute expiration of 1 minute
            _cache.Add(key, item);

            // Print output on console
            Console.WriteLine("\nObject is added to cache.");
        }

Und wenn Sie das einmal getan haben, können Sie es auch tun _cache.Get und das gleiche Objekt zurückbekommen. Wenn Sie das also im Hinblick auf die API sehen würden, finden Sie hier Folgendes Cache.Get, Get, Enthält, Hinzufügen, Einfügen, Entfernen und alle drei haben eine asynchrone Version, was im Grunde bedeutet, dass die Anwendung nicht auf die Aktualisierung des Caches wartet, sondern die Kontrolle sofort zurückerhält. Der Schlüssel ist jedoch normalerweise eine Zeichenfolge. Normalerweise handelt es sich dabei um etwas Ähnliches. Sie haben den Typnamen. Im Falle von NCache das hängt davon ab. Wenn Sie diese Funktion verwendet haben, rufen Sie an Client-Cache. Also werde ich einfach darauf eingehen.

Client-Cache (in der Nähe von Cache)

Sie gehen also standardmäßig davon aus, dass jedes Mal, wenn Sie Folgendes tun: Cache.Get, gelangen Sie tatsächlich zur Caching-Ebene. Es gibt jedoch eine interessante Sache, die den meisten Menschen nicht bewusst ist: Wenn Sie einen In-Proc-Cache wie das ASP.NET-Cache-Objekt verwendet haben und sich entschieden haben, auf etwas wie … umzusteigen NCache weil wir gesagt haben, dass es Ihre Leistung und Skalierbarkeit verbessern wird. Nun, es dient der Verbesserung der Skalierbarkeit, aber plötzlich wird Ihre Leistung tatsächlich sinken. Wir haben viele Kunden, die uns anrufen und sagen: Wissen Sie, meine Anwendung ist tatsächlich langsamer geworden, seit ich sie angeschlossen habe NCache. Also, warum brauche ich es wirklich? Es ist wirklich nicht gut, es ist ein... du weißt schon. Dann müssen wir ihnen erklären, dass es bei einem In-Proc-Cache keine Serialisierung und keine prozessübergreifende Kommunikation zwischen der Anwendung und dem Cache gibt, unabhängig davon, ob dieser sich auf derselben Box oder in einer separaten Box befindet, normalerweise ist es eine separate Box, rechts. Wenn das Objekt also in Objektform auf Ihrem Heap gespeichert wird, ist es superschnell, richtig. Gehen Sie einfach hin und holen Sie sich eine Referenz. Mit dieser Leistung kann nichts mithalten. Der Grund für die Umstellung auf einen verteilten Cache liegt jedoch darin, dass dieses In-Proc-Modell viele Einschränkungen aufweist. Es kann nicht skaliert werden. Sie können nicht immer mehr Daten hinzufügen, es ist nur ein Prozess und wenn Sie mehr als einen Prozess haben, wird die Duplizierung nicht synchronisiert. Es gibt also viele andere Probleme, weshalb Sie zu einem verteilten Cache wechseln, aber Sie verlieren diesen Vorteil, richtig. Was wir also gemacht haben, ist, dass wir etwas namens Client-Cache entwickelt haben, das auf der Java-Seite „Near Cache“ heißt und auf der .NET-Seite „Time and Cache“ das einzige ist, das es hat.

Cache-Statistiken

Was dies also tatsächlich bewirkt, ist die Erstellung eines lokalen In-Proc-Cache innerhalb der Anwendung. Das Objekt bleibt also in einer Objektform auf Ihrem Heap. Sie erhalten also die gleiche Leistung, die Sie vom eigenständigen In-Proc-Cache gewohnt sind. Der einzige Unterschied besteht darin, dass dieser Cache weiß, dass er Teil eines Cluster-Cache ist. Was auch immer es in seiner lokalen Kopie behält, es hat einen Link zur Caching-Ebene. Es hat der Caching-Ebene mitgeteilt, dass ich dieses Objekt habe. Bitte benachrichtigen Sie mich, wenn jemand dieses Objekt ändert. Nehmen wir also an, wenn überhaupt, hat dieser Kunde die Artikelnummer eines anderen Kunden und natürlich befindet sich dieser Artikel Nummer eins auch in dieser Caching-Ebene. Ein anderer Kunde kommt herein und aktualisiert den Artikel Nummer eins. Die Caching-Ebene weiß, dass diese Client-Caches das Element Nummer eins haben, also benachrichtigen sie dies über Ereignisse, wissen Sie. Im Falle von NCache Es sind ziemlich schnelle Ereignisse. Hierbei handelt es sich nicht um .NET-Ereignisse, sondern um Kommunikation auf Socket-Ebene. Der Client-Cache aktualisiert sich also sofort selbst. Wir sprechen also vielleicht von einer Verzögerung im Millisekundenbereich.

Auf diese Weise können Sie sicher sein, dass das, was Sie erhalten, vollständig oder größtenteils korrekt ist. Technisch gesehen besteht eine geringe Wahrscheinlichkeit, dass es sich möglicherweise um eine ältere Kopie handelt. Im Falle von NCache, wenn Sie sich darüber zu viele Sorgen machen, können Sie den sogenannten pessimistischen Synchronisierungsmodus verwenden, bei dem Sie jedes Mal, wenn Sie etwas abrufen, wissen Sie: NCache Überprüft intern die Caching-Ebene, ob eine aktuelle Kopie vorhanden ist. Wenn dies nicht der Fall ist, werden die Daten aus dem Client-Cache bereitgestellt, andernfalls werden sie aus der Cache-Ebene abgerufen. In den meisten Fällen ist dies jedoch nicht erforderlich. In den meisten Fällen ist es in Ordnung, so viel Risiko einzugehen. Dadurch erhalten Sie die Leistungssteigerung des In-Proc-Cache. Aber auch hier weiß Ihre Anwendung nicht, dass all dies geschieht.

Im Falle von NCache Ihre Bewerbung weiß es. Die Anwendung geht davon aus, dass sie nur mit der Caching-Ebene kommuniziert. Es gibt nur einen Cache, mit dem es kommuniziert. Es heißt mein Cache oder so. Es handelt sich um den Demo-Cache, und in den Demo-Cache kann über die Konfiguration ein Client-Cache eingebunden werden NCache. Haben Sie Fragen dazu?

JCache (JSR 107)-API

Ich meine, so sieht ein typischer Cache aus. Es ist ziemlich einfach, diese Programmierung durchzuführen. Was passiert jetzt auf der Java-Seite? Auch hier lobe ich sie immer wieder, weil sie in diesem Bereich viel weiter fortgeschritten sind. Sie haben eine ganze Standard-API namens JCache. Die JCache-API ist also eine sehr wichtige Funktion … sie verfügt über alle Funktionen, über die ich gerade gesprochen habe oder über die ich spreche. JCache ist also ein Standard, den jeder Java-Cache implementieren muss, wenn er mit der Branche kompatibel sein möchte.

IDistributedCache-API

Auf der .NET-Seite gibt es so etwas noch nicht. Es gibt ein ASP.NET-Cache-Objekt, das bis vor kurzem nicht steckbar war. Wenn Sie also für den ASP.NET-Cache programmieren, können Sie keine Verbindung herstellen NCache stattdessen. Sie können also keinen Drittanbieter-Cache anschließen. Es ist nur ein eigenständiger Cache. In .NET 4.0 wurde ein .NET-Cache gestartet, der nie wirklich funktionierte. Jetzt in ASP.NET core Sie haben eine iDistributedCache Schnittstelle. Dabei handelt es sich wiederum um eine sehr einfache Just-Get-Input-Methode.

Das Problem mit der Standard-API besteht also darin, dass Sie nicht alle Funktionen nutzen können, die Ihnen ein guter Cache bieten sollte. Sie sind wirklich auf die grundlegenden Eingaben beschränkt. Aber auch hier kapseln die meisten unserer Kunden die Caching-Ebene ohnehin. Also, selbst wenn sie das alles machen NCache Bei Aufrufen ist nicht die gesamte Anwendung davon betroffen. So sieht die API jedenfalls aus.

App-Daten-Caching-Funktionen

Gehen wir nun auf einige der wichtigen Funktionen ein. Also, die meisten von ihnen … machen weiter. Nur eine einfache Frage. Gibt es einen Unterschied zwischen Einfügen und Hinzufügen? Ja, Einfügen bedeutet Hinzufügen oder Aktualisieren. Wenn die Daten bereits vorhanden sind, aktualisieren Sie sie. Wenn nicht, fügen Sie sie hinzu. Das Hinzufügen schlägt fehl, wenn die Daten bereits vorhanden sind. Und auch hier handelt es sich um eine ASP.NET-Cache-API, an der wir irgendwie festgehalten haben, weil wir dem damaligen Standard möglichst nahe kommen wollen. Nein, nein, ist es nicht. Ich meine, wir haben es behalten. Das ASP.NET-Cache-Objekt ist jetzt nicht mehr da, wie gesagt, im ASP.NET Core ist nicht mehr da, ASP.NET hat es immer noch, aber ASP.NET Core nicht.

Absolute Ablauffristen

Das erste, was Sie im Auge behalten müssen, ist, den Cache frisch zu halten, worüber wir gesprochen haben, richtig. Wie Sie diese Technik Nummer eins anwenden, sind Ablauffristen. Der Ablauf sieht in etwa so aus, lasst uns darauf zurückkommen. Nehmen wir an, ich habe … Könnt ihr das sehen? Kannst du das sehen? OK. Nehmen wir an, ich habe einen Schlüssel und einen Wert oder ein Objekt. Ich möchte es zum Cache hinzufügen und gebe einen Ablauf von 1 Minute an. Das nennt man also absoluter Ablauf.

public static void AddObjectToCache(string key, Customer customer)
    {
        DateTime expirationInterval = new DateTime();
        expirationInterval.AddMinutes(1);
        //Adding item with an absolute expiration of 1 minute
        _cache.Add(key, customer, expirationInterval, Cache.NoSlidingExpiration, CacheItemPriority.Normal);
        Console.WriteLine("\nObject is added to cache");
    }

Der absolute Ablauf bedeutet, dass dieser nach Ablauf von 1 Minute auf jeden Fall abläuft. Das heißt, ich sage dem Cache, ich fühle mich wirklich nicht wohl dabei, dies länger als eine Minute zwischenzuspeichern. Denn ich gehe davon aus, dass es sicher ist, dies eine Minute lang im Cache zu behalten.

Gleitende Ablauffristen

Der gleitende Ablauf hingegen hat einen ganz anderen Zweck. Es dient der Bereinigung von Dingen wie Sitzungen. Es hat nichts mit der Synchronisierung oder dem Frischhalten des Caches zu tun. Absoluter Ausdruck ist also etwas, was fast alle Caches haben. Tatsächlich sogar der ASP.NET Core Die IDistributed-Cache-Schnittstelle hat den absoluten Ausdruck.

Cache mit Datenbank synchronisieren

Aber was ist falsch daran, dass Ausdruck die einzige Möglichkeit ist, Cache zu erstellen oder den Cache frisch zu halten? Sie gehen davon aus, dass sich diese Daten nicht ändern werden. Was ist, wenn das der Fall ist? Was ist, wenn es andere Anwendungen und andere Skripte gibt, die die Daten ändern, und in jedem Unternehmen gibt es normalerweise mehr als einen Ort, an dem die Daten aktualisiert werden? Wenn Sie also nicht vorhersagen können, wie oft die Daten aktualisiert werden, sind Ausdrücke nur ein Ausgangspunkt. Sie müssen mit dem nächsten Schritt fortfahren, nämlich dem Synchronisieren des Caches mit der Datenbank. Sie müssen also im Grunde genommen den Cache mit der Datenbank synchronisieren, falls dies der Fall ist NCache Wir verwenden diese Funktion, die Teil von ADO.NET .NET ist und als SQL-Abhängigkeit bezeichnet wird.

Im Wesentlichen handelt es sich um eine SQL-Abhängigkeit. Lassen Sie mich Ihnen zeigen, wie das aussieht. Im Falle einer SQL-Abhängigkeit mache ich also den gleichen Cache.Add, richtig. Ich habe den Schlüssel und anstelle des Werts habe ich ein Cache-Element, das unsere eigene Struktur ist, in die wir das eigentliche Objekt einfügen, und jetzt haben wir das und dann spezifizieren wir dieses Ding namens SQL-Abhängigkeit, SQL-Server-Abhängigkeit, das ist diese Variable, die im Wesentlichen die SQL-Anweisung erstellt.


private static void AddProductToCacheWithDependency(Product product)
    {
        // Any change to the resultset of the query will cause cache to invalidate the dependent data
        string queryText = String.Format("SELECT ProductID, ProductName, QuantityPerUnit, UnitPrice FROM dbo.PRODUCTS WHERE PRODUCTID = {0}", product.Id);

        // Let's create SQL depdenency
        CacheDependency sqlServerDependency = new SqlCacheDependency(_connectionString, queryText);

        CacheItem cacheItem = new CacheItem(product);
        cacheItem.Dependency = sqlServerDependency;

        // Inserting Loaded product into cache with key: [item:1]
        string cacheKey = GenerateCacheKey(product);
        _cache.Add(cacheKey, cacheItem);
    }

Dieser Code wird hier auf der Client-Box ausgeführt.

Cache-Statistiken

Es kommuniziert mit dem Cache-Server. Es weist den Cache-Server an, die ADO.NET SQL-Abhängigkeitsfunktion zu verwenden, um eine Verbindung zu meiner Datenbank herzustellen. Es gibt mir also tatsächlich eine Verbindungszeichenfolge zur Datenbank. Nun teilt die Anwendung dem Cache mit, hier ist meine Datenbank für dieses zwischengespeicherte Element, hier ist die SQL-Anweisung, die die entsprechenden Daten in der Datenbank darstellt.

Entity Framework/Entity Framework Core-Integration

Gute Frage. Im Fall von Entity Framework haben wir die Implementierung, die wir für Entity Framework haben, intern implementiert. Selbst mit Entity Framework gibt es zwei Möglichkeiten, einen Cache zu verwenden. Entweder Sie, im Fall von EF Core ermöglicht die neue Architektur jetzt das Einbinden des Drittanbieter-Cache, aber bis EF6 gab es keine Möglichkeit, einen Cache einzubinden. Sie müssten diese API-Aufrufe also ohnehin durchführen. Nehmen wir also an, Sie haben eine Sammlung von Entitäten zurück und können beim Zwischenspeichern dieser Entitäten die SQL-Abhängigkeit angeben. Hast du verstanden, was ich meinte?

Im Falle von NCache du erzählst NCache Hier ist meine SQL-Anweisung. NCache Wir verwenden ADO .NET, um eine Verbindung zu Ihrer Datenbank herzustellen, und verwenden die ADO.NET SQL-Abhängigkeitsfunktion, um diesen Datensatz anschließend zu überwachen. So, NCache teilt SQL Server mit, bitte benachrichtigen Sie mich, wenn sich dieser Datensatz ändert. Anschließend sendet der SQL Server eine Datenbankbenachrichtigung an NCache weil NCache ist kein Client der Datenbank und dann NCache weiß nun, dass sich diese Daten in der Datenbank geändert haben. Obwohl Sie EF hatten, wird das und jetzt das irgendwie umgangen NCache weiß, dass sich diese Daten geändert haben NCache hat zwei Möglichkeiten. Zum einen kann es entweder das Element aus dem Cache entfernen und wenn Sie es entfernen, wissen Sie, dass jemand es das nächste Mal, wenn er es benötigt, nicht im Cache finden wird, also muss er es aus der Datenbank holen. In gewisser Weise machen Sie es also frisch oder NCache kann diese Daten für Sie aus der Datenbank selbst neu laden, und das ist nicht möglich, es sei denn, Sie verwenden eine andere Funktion namens „Durchlesen“, darauf komme ich noch zurück.

Die SQL-Abhängigkeit stellt also grundsätzlich sicher, dass Sie es einfach sagen, wenn Sie nicht vorhersagen können, wann sich die Daten ändern könnten NCache oder Ihren Cache, bitte überwachen Sie die Datenbank für mich.

Bei SQL-Abhängigkeiten besteht die Einschränkung, dass darin keine Verknüpfungen möglich sind. Es handelt sich also um eine Einzeltischsache. Es gibt andere Möglichkeiten zur Überwachung. Zum Beispiel im Falle von NCache Es gibt eine Funktion namens Benutzerdefinierte Abhängigkeit, das ist Ihr Code. NCache ruft Ihren Code auf und sagt: Bitte überwachen Sie Ihre Datenquelle und prüfen Sie, ob sich Daten geändert haben. Das ist also so etwas wie eine Umfrage. So, NCache wird Ihre benutzerdefinierte Abhängigkeit abfragen und dann könnte es sich um eine komplexe Struktur handeln.

Ja genau. Wenn Sie die SQL-Abhängigkeit ausführen, kommuniziert der Cache tatsächlich nicht so häufig mit der Datenbank, weil er nur … Die Datenbank ist also diejenige, die die Kommunikation initiiert, weil ein Ereignis vorliegt. Es handelt sich um eine ereignisgesteuerte Architektur. Daher sendet die Datenbank jedes Mal ein Ereignis, wenn sich die Daten ändern.

Tatsächlich verfügt der SQL-Server über diese Funktion, mit der er den Datensatz überwacht und dann Datenbankbenachrichtigungen an die Clients sendet. So, NCache wird zum Datenbank-Client.

Eine Möglichkeit bestand also darin, das Element aus dem Cache zu entfernen. Die andere besteht darin, es einfach neu zu laden. Nun, Nachladen bedeutet das NCache Es muss eine Möglichkeit geben, zu wissen, wie man diese Daten abruft, und das bedeutet, dass es diese Funktion namens „Durchlesen“ gibt, bei der es sich um Ihren Code handelt, den Sie schreiben und beim Cache-Server, dem Cache-Cluster, registrieren. Ich zeige Ihnen schnell, wie dieser Code aussieht.

Read-Through-Cache

Nein, eigentlich ist es nur Ihr benutzerdefinierter Code. Sie können die ORM-Aufrufe also auch innerhalb dieses Codes durchführen. Der Code sieht also nur so aus. Hier gibt es also eine IReadThruProvider-Schnittstelle.

...
// Perform tasks like allocating resources or acquiring connections
public void Init(IDictionary parameters, string cacheId)
{
    object connString = parameters["connstring"];
    sqlDatasource = new SqlDatasource();
    sqlDatasource.Connect(connString == null ? "" : connString.ToString());
}

// Perform tasks associated with freeing, releasing, or resetting resources.
public void Dispose()
{
    sqlDatasource.DisConnect();
}

// Responsible for loading an object from the external data source.
public ProviderCacheItem LoadFromSource (string key)
{
    ProviderCacheItem cacheItem = new ProviderCacheItem(sqlDatasource.LoadCustomer(key));
    cacheItem.ResyncOptions.ResyncOnExpiration = true;
    // Resync provider name will be picked from default provider.
    return cacheItem;
}
...

Es gibt also die IReadThruProvider-Schnittstelle. Es gibt drei Methoden. Es gibt einen Init, der nur aufgerufen wird, wenn der Cache startet. Es soll also eine Verbindung zu Ihrer Datenquelle herstellen. Es gibt eine Entsorgung am Ende und eine Ladung. Load gibt Ihnen also einen Schlüssel und Sie sollen ein Cache-Element zurückgeben.

Basierend auf diesem Schlüssel muss Ihr Code also wissen, wohin er gehen muss, da er bereits eine Verbindung zu Ihrer Datenquelle hergestellt hat. Egal, ob Sie ORM verwenden, ob Sie EF-Aufrufe, NHibernate-Aufrufe oder ADO.NET-Aufrufe durchführen, das ist Ihr gesamter Code, und dann laden Sie ihn, sagen wir, Sie laden dieses Objekt aus der Datenbank und Sie Fügen Sie es ein, geben Sie Ablaufdaten oder andere gewünschte Metadaten ein und geben Sie es zurück NCache. NCache speichert es dann zwischen, bevor es an die Anwendung zurückgegeben wird.

Also, der ganze Zweck des Durchlesens … lassen Sie mich gleich zu diesem Durchlesen selbst kommen. Das Durchlesen ist eine Möglichkeit für den Cache, Daten aus Ihrer Datenbank zu laden. Sie verschieben also tatsächlich einen Teil Ihres Persistenzcodes in die Caching-Ebene. Und wenn Sie mehrere Anwendungen haben, die einen Cache gemeinsam nutzen möchten, ist ein Lese- und Schreibmechanismus ideal. Durch die Konsolidierung erstellen Sie die Anwendungen, also weniger Code, wissen Sie. Sie verfügen also über weniger Code, da immer mehr Persistenzcode in die Caching-Ebene gelangt. Das ist ein Vorteil. Sie wissen schon, Kapselung und Konsolidierung.

Der zweite Vorteil des Durchlesens ist das, worüber wir gerade beim Neuladen gesprochen haben. Ein Neuladen erfolgt also in zwei Fällen. Einer befindet sich in der Datenbanksynchronisierung, der andere im Ablauf. Der Ablauf ist auch ein guter Fall, wenn Sie eine Anwendung mit sehr hohem Datenverkehr haben, die beispielsweise über eine Art Nachschlagetabelle oder Preistabelle verfügt, die sich ändert, und in der Tausende von Anfragen eingehen. Wenn Sie nicht über die Neuladefunktion verfügen, werden bei Ablauf der Daten Tausende dieser Anfragen in die Datenbank eingehen. Und sie laden alle dasselbe Objekt in den Cache. Was letztendlich nur viel Verkehr zur Datenbank bedeutet. Wenn Sie das mit Tausenden von Elementen multiplizieren, wird Ihre Datenbank möglicherweise viel unnötigen Datenverkehr verzeichnen.

Einer unserer Kunden ist tatsächlich ein High-End-E-Commerce-Kunde im Blumengeschäft in den USA und hatte dieses Problem. Als sie also die Neuladefunktion implementierten, verschwand das ganze Problem plötzlich, da das Element nun nie mehr aus dem Cache entfernt wird. Die alten Kopien bleiben also bis zu einem bestimmten Zeitpunkt erhalten und die neue Kopie wird darüber aktualisiert. Die Anwendung muss also nie auf die Datenbank zugreifen. Denn selbst bei der Erkundung wird lediglich die neue Kopie aktualisiert. Es sind also viele … Das sind also die beiden Vorteile, die Sie mit dieser Synchronisierung kombinieren können.

Durchschreibcache

Der andere Aspekt ist das Durchschreiben, das genau wie das Durchlesen funktioniert, außer dass es sich um das Schreiben handelt und ein Schreiben entweder hinzugefügt, eingefügt oder gelöscht oder entfernt werden kann. Nochmals, auf die gleiche Weise haben Sie Init, Sie haben Dispose und jetzt haben Sie es WriteToDataSource. Darin wird angegeben, um welche Operation es sich handelt, und es sind auch die Daten enthalten. Anschließend können Sie die Datenbank aktualisieren. Durchschreiben bedeutet also, dass Sie den Cache aktualisieren und der Cache die Datenbank aktualisiert.

Was ist also der Vorteil des Durchschreibens? Nun, ein Vorteil ist der gleiche wie beim Durchlesen. Sie festigen die ganze Beharrlichkeit. Zweitens liegt der Nutzen im Write-Behind. Denn die Datenbankaktualisierungen sind nicht so schnell wie die, und wenn Sie darauf vertrauen, dass die Datenbankaktualisierung erfolgreich sein wird, aktualisieren Sie einfach den Cache und lassen Sie den Cache die Datenbank asynchron aktualisieren. Natürlich können Sie benachrichtigt werden, wenn etwas fehlschlägt, aber Sie können weitermachen und andere Dinge tun, was auch die Aktualisierungsleistung Ihrer Anwendung verbessert. Jetzt müssen Sie nicht mehr warten, bis die Datenbankaktualisierungen abgeschlossen sind, da sie alle in der Warteschlange stehen. Das ist also der Write-Behind-Teil. Und die Write-Behind-Warteschlange wird erneut auf mehr als einen Server repliziert. Wenn also ein Server ausfällt, geht in diesem Fall keiner Ihrer Vorgänge verloren NCache.

Aber das ist Ihr Code. Ich meine NCache ruft deinen an. Das alles ist also Ihr Code. So, NCache ruft Sie an und Sie finden heraus, was das Schreiben bedeutet oder was das Lesen bedeutet.

Das Durchlesen und Durchschreiben ist also eine weitere sehr leistungsstarke Funktion, die Sie mit Ablauf und Synchronisierung kombinieren können. Sie müssen also sicherstellen, dass der Cache frisch bleibt, und dann müssen Sie sicherstellen, dass Sie die Durchlese- und Durchschreibfunktion verwenden. Nachdem Sie damit begonnen haben, können Sie viele Daten zwischenspeichern. Und jetzt sieht dieser Cache allmählich wie die Datenbank aus. Das bedeutet, dass Sie nicht wirklich wissen, dass der Schlüssel jetzt nicht ausreicht. Sie müssen in der Lage sein, eine Suche durchzuführen. Sie müssen in der Lage sein, Dinge intelligenter abzurufen. Hier sollten Sie also in der Lage sein, SQL-Abfragen für den Cache durchzuführen. Zum Beispiel so etwas wie „Kunden auswählen“, wobei der Kundenpunkt „Stadt“ gleich „London“ ist. Sie erhalten eine Sammlung aller Kundenobjekte zurück, die diesen Kriterien entsprechen. Und der Cache indiziert diese Objekte beispielsweise basierend auf dem Stadtattribut. Auf diese Weise können Sie also suchen.

Wenn Sie dazu nicht in der Lage sind, wird Ihre Anwendung komplexer, da Sie nur nach Schlüsseln suchen können und Sie wissen, dass Sie es gewohnt sind, mit der Datenbank viele andere Dinge zu tun, die Ihnen nicht möglich sind mit dem Cache machen.

Es gibt keine Verknüpfungen in einem Cache, aber Sie können Gruppierungen vornehmen. Und das dient in gewisser Weise diesem Zweck, indem man Daten erhält und sie dann irgendwie gruppiert und dann basierend auf diesen Gruppen sagen kann: „Gebt mir alles, was zu diesen Gruppen, Untergruppen, Tags, Namens-Tags gehört.“ Es gibt also noch andere Dinge, die Sie tun können, um Dinge logisch zu gruppieren, und die Daten selbst, die Sie zwischenspeichern, können über Verknüpfungen bereitgestellt werden. Es ist nur so, dass der Cache nicht sein kann … der Cache ist keine Suchbasismaschine. Wenn Sie also Join-Daten haben, gruppieren Sie diese einfach.

Cache-Abhängigkeiten

Es gibt also ein Feature und noch einmal, weil es so viel davon gibt, das ich in dieser Zeit nicht wirklich behandeln kann. Es gibt also eine Funktion namens Cache-Abhängigkeit was übrigens aus dem ASP.NET-Cache-Objekt stammt, NCache hat auch implementiert, was ermöglicht … Sie teilen dem Cache mit, dass dieses Element von diesem Element abhängt. Wenn dieses Element jemals aktualisiert oder entfernt wird, wird dieses automatisch entfernt. Wenn Sie also diese Beziehungen erstellen, können Sie eine Eins-zu-Viele-Beziehung haben, sagen wir, wenn Sie eine Eins-zu-Viele-Beziehung hätten, in der die Viele-Seite ohne die Eine-Seite nicht existieren kann. Nehmen wir an, es handelt sich um einen Kunden und eine Bestellung. Wenn Sie also den Kunden entfernen, möchten Sie auch die Bestellung entfernen. Sie können das also dem Cache überlassen. Wenn Sie beispielsweise eine Sammlung von Objekten zwischenspeichern, können Sie entweder die gesamte Sammlung als ein Objekt zwischenspeichern oder sie in einzelne Objekte aufteilen. Wenn Sie sie aufteilen, möchten Sie die Cache-Abhängigkeiten erledigen. Wenn also ein Objekt entfernt wird, ist diese Sammlung nicht mehr gültig.

Ja, das ist also ein ganzes Thema, zu dem ich einen Vortrag halte, zu dem Sie auf unsere Website kommen können. Lassen Sie mich es Ihnen kurz zeigen. Es gibt also eine ganze Diskussion darüber. Ich denke es ist Umgang mit relationalen Daten in einem Cache. Das geht also über alle Eins-zu-Viele, Eins-zu-Eins, Viele-zu-Viele, das geht über Sammlungen und all das Zeug, über das Sie gerade gesprochen haben. Schauen Sie sich das einfach mal an. Ich werde es nur schnell durchgehen, weil wir keine Zeit mehr haben.

Ich habe also versucht, darzulegen, warum Sie einen Cache verwenden sollten und wie Sie ihn nutzen und den Nutzen daraus maximieren sollten. Ich werde das überspringen gemeinsame Nutzung von Laufzeitdaten Teilweise denke ich, dass ich genug abgedeckt habe. Sie können unsere Website besuchen und mehr darüber erfahren. Ich habe über den Client-Cache gesprochen, ich habe über die hohe Verfügbarkeit durch Partitionierung und all das gesprochen.

WAN-Replikation des verteilten Caches

Es gibt auch mehrere Rechenzentren. Sie erwarten, dass Ihre Datenbank mehrere Rechenzentren verwalten kann. Warum also nicht der Cache? Also nochmal, NCache bietet Ihnen diese Funktion. Auf der Java-Seite gibt es Caches, die dies tun. Auf der .NET-Seite NCache ist der Einzige. Sie können also ein Aktiv-Passiv- oder ein Aktiv-Aktiv-Rechenzentrum haben und die Caches werden synchronisiert. Auch hier gilt: Es ist nicht möglich, einen Cluster über das WAN zu spannen, da die Leistung einfach nachlässt. Sie müssen eine asynchrone Replikation oder Synchronisierung über das WAN durchführen, da sich zwei Rechenzentren möglicherweise nicht am selben Standort befinden.

WAN-Replikation

Einer von uns Kunden ist Ryanair, eine große Fluggesellschaft hier, die über Rechenzentren in Dublin, London und Frankfurt verfügt. Sie müssen also sicherstellen, dass sie synchronisiert werden können. Im Falle von NCache wir haben auch WAN-Replikation. Es gibt auch ein Multi-Datacenter-Sitzungskonzept, bei dem die Sitzung von einem Datacenter zum anderen verschoben werden kann. Aber auf jeden Fall muss Ihr Cache in der Lage sein, mehrere Rechenzentren zu unterstützen. Schauen Sie sich das also unbedingt an.

NCache vs Redis

Die meisten .NET-Leute wissen davon Redis. NCacheEs tut mir leid, Microsoft hat sie jedoch als ihre Wahl für Azure ausgewählt Redis kommt aus einem Linux-Hintergrund. Ich denke, der Hauptgrund, warum Microsoft sie ausgewählt hat, ist, dass sie mehrere Sprachen haben wollten. So, Redis deckt viele Sprachen ab. NCache ist ziemlich stark auf .NET ausgerichtet. Wir haben aber auch eine Java-API NCache selbst ist auf .NET ausgerichtet. Ich möchte einen sehr kurzen Überblick über die beiden geben, damit Sie verstehen, was das bedeutet. Wenn Sie dann auf unsere Website gehen, sehen Sie tatsächlich ein vollständiges Bild Vergleich. Hier können Sie einen Funktionsvergleich durchführen. Und dann können Sie dies auch herunterladen. Schauen Sie sich das also unbedingt an. Es basiert auf ihrer und unserer Dokumentation. Es ist also nichts anderes als … da ist nichts dran.

NCache ist auch Open Source, also auch Redis. Im Falle von NCache Sie haben die … Sie können auf unsere Website kommen und Sie können herunterladen entweder die Enterprise Edition oder die Open Source, oder Sie können auch zu GitHub gehen, wo es ist NCache? Genau hier GitHub und dann kannst du sehen NCache hier auch.

Daher wird diese Enterprise-Edition vollständig unterstützt. Im Falle von Redis Microsoft portiert Redis von Linux zu Windows. Man könnte also meinen, dass Microsoft den Port in Azure verwenden würde, aber das ist nicht der Fall. Der Port, den sie haben, weist also viele Probleme auf. Viele Kunden haben sich darüber bei uns beschwert.

Also, wenn Sie verwenden Redis In Azure verwenden sie die Linux-Version. Sie ist stabil, es gibt kein Problem damit, aber Sie verlieren alle Funktionen, über die wir gerade gesprochen haben. Wenn Sie einen On-Premise-Support durchführen möchten, NCache Sie erhalten entweder Open Source, alles ist kostenlos, Enterprise ist etwas, bei dem Sie mehr Funktionen erhalten, als Sie auch für den Support bezahlen. Wenn Sie vor Ort mit möchten Redis, die einzige Möglichkeit, die Sie haben, ist die Linux-Version von Redis Labore. Sie haben dies jetzt auch im Docker. Sie können es also technisch gesehen unter Windows ausführen, aber immer noch die Linux-Umgebung für sie verwenden. Die On-Prem-Version von Windows stammt von Microsoft, was wie gesagt instabil und ohne Support ist.

In Azure Redis gibt Ihnen ein Cache-Service-Modell, NCache gibt Ihnen ein VM-Modell. Das VM-Modell gibt Ihnen viel mehr Kontrolle. All diese Dinge, über die wir gerade gesprochen haben: Durchlesen, Durchschreiben, Cache-Loader, Datenbanksynchronisierung, Sie erhalten die gesamte Kontrolle und es gibt nur eine Client-API.

Das ist nur ein kurzer Überblick über die beiden. Ich wollte es irgendwie erwähnen. Grundsätzlich, NCache ist der älteste Cache im .NET-Bereich. Unzählige Kunden nutzen es NCache. Viele davon befinden sich auch in Großbritannien. Wissen Sie, Großbritannien ist unser zweitgrößter Markt, und wenn Sie eine .NET-Anwendung haben, hoffe ich, dass Ihnen der gesamte Stack lieber .NET ist. NCache gibt Ihnen den .NET-Stack, Redis nicht.

Haben Sie noch Fragen, bevor ich diesen Vortrag abschließe? Aber dann legen Sie die Partitionierung selbst offen. Denn in einer relationalen Datenbank muss man die Anwendung dann so programmieren, dass die Daten in der einen oder anderen Datenbank gespeichert sind. Ich meine, das ganze Konzept von No SQL besteht darin, dass sie das Sharding für Sie erledigen, weil alles auf dem Schlüssel basiert. In einer relationalen Datenbank ist die Komplexität viel größer, und bisher war keine der relationalen Datenbanken in der Lage, das Problem der Skalierbarkeit zu lösen. Sie haben sich sehr viel Mühe gegeben und ihre Leistung enorm verbessert. Es gibt viele In-Memory-Optionen, also verfügen sie auch über In-Memory-Datenbanken und sie führen viele In-Memory-Tabellen und so weiter. Die Leistung hat sich also erheblich verbessert, aber die Leistung ist hier nicht das Problem. Wissen Sie, das Problem ist die Skalierbarkeit. Können Sie diese Last bewältigen und bisher können sie es nicht.

Der Grund für die Indizierung besteht also darin, dass Sie nach diesen Attributen suchen können. Sie könnten also eine SQL-Anweisung ausführen und nach den Attributen des Objekts suchen, für das Sie einen Index erstellt haben.

Wir erlauben Ihnen also keine Suche, es sei denn, Sie haben den Index erstellt. Also, wenn Sie eine Suche durchführen NCache löst eine Ausnahme aus, die besagt, dass dieses Attribut nicht indiziert wurde. Also irgendwie auf eine schmerzhaftere Art und Weise, ja. Aber was wir unseren Kunden sagen: Sie müssen einen Index erstellen, egal, wonach Sie suchen möchten. Und im Gegensatz zu einer Datenbank, in der alles SQL ist, läuft hier nicht alles über SQL. Auch hier erledigen Sie viele Dinge nur über die API und einiges davon über SQL.

Du meinst für den Cache-Namen? Es gibt eine Konvention, dass der Schlüssel die Typinformationen enthalten und dann auf bestimmten basieren sollte, sagen wir, wenn es sich um ein einzelnes Objekt und den Typ und entweder den Primärschlüsselwert oder den Primärschlüsselattributnamen und dann den Wert handelt, das ist die übliche Sache, und wenn Sie dann die gesamte Sammlung speichern, sagen wir, Sie speichern alle anderen Bestellungen für den Kunden und möchten sie dann möglicherweise basierend auf dem Kunden abrufen, dann kann der Schlüssel Kunde, Kunden-ID, meine Bestellungen oder so etwas sein, wissen Sie. Die Schlüssel müssen also aussagekräftig sein, je nachdem, wie Sie die Daten abrufen möchten.

Ja, all das sind Optionen, die Sie wählen können. Wenn Sie sich mein Video zum Umgang mit relationalen Daten ansehen, gehe ich alle diese Optionen durch. Und noch einmal beim Caching: Nehmen wir an, Sie haben eine Viele-zu-Viele-Beziehung in der Datenbank. Auf Anwendungsebene gibt es nicht viele zu viele. Bei der Bewerbung nähern Sie sich entweder von dieser Seite oder von dieser Seite. Es ist immer eins zu viele. Es kommt also vor, dass sich plötzlich die Perspektive ändert.

Sie versuchen nicht, die gesamte Datenbank im Speicher neu zu erstellen. Können Sie die Vorteile der Verwendung eines verteilten Caches zusammenfassen? Sie sagten, es liege an der Skalierbarkeit. Gibt es noch andere? Ich denke, der wichtigste Vorteil ist die Skalierbarkeit. Der sekundäre Vorteil ist die Leistung und wiederum gibt es für die Anwendungsfälle, für die ASP.NET-spezifischen Anwendungsfälle, die Sitzungen, einen enormen Vorteil. Denn die Alternativen zu einem verteilten Cache sind alle sehr langsam oder nicht skalierbar. Wenn Sie also einen In-Proc durchführen, ist dieser nicht skalierbar. Denn Sie müssen jedes Mal den gleichen Prozess durchlaufen.

Ich zeichne das auch auf und ich denke, das gilt auch für die SDD-Konferenz. Wir werden diesen Vortrag auf YouTube veröffentlichen. Wenn Sie an unseren Stand kommen und sich von uns scannen lassen, können wir Ihnen den Link zum Vortrag per E-Mail zusenden und Sie können ihn dann mit Ihren Kollegen teilen. Vielen Dank Jungs für eure Geduld.

Was macht man als nächstes?

 

Melden Sie sich für den monatlichen E-Mail-Newsletter an, um die neuesten Updates zu erhalten.

© Copyright Alachisoft 2002 - Alle Rechte vorbehalten NCache ist eine eingetragene Marke der Diyatech Corp.