Was ist Memcache?
Cache -Lösung in der Memcache -Cluster -Umgebung
Memcache ist ein Hochleistungs-Verteilungs-Speicher-Objekt-Cache-System. Durch die Aufrechterhaltung einer einheitlichen und riesigen Hash -Tabelle im Speicher kann sie verwendet werden, um Daten in verschiedenen Formaten zu speichern, einschließlich Bildern, Videos, Dateien und Datenbankabrufergebnissen. Einfach ausgedrückt, es soll die Daten in den Speicher aufrufen und sie dann aus dem Speicher lesen, wodurch die Lesegeschwindigkeit erheblich verbessert wird.
Memcache ist ein Projekt in Danga. Es wurde zum ersten Mal von LiveJournal serviert. Es wurde ursprünglich entwickelt, um die Zugangsgeschwindigkeit von LiveJournal zu beschleunigen. Es wurde später von vielen großen Websites übernommen.
Memcached läuft auf einem oder mehreren Servern in einem Daemon -Modus und empfängt jederzeit Client -Verbindungen und -vorgänge.
Warum gibt es zwei Namen Memcache und Memcached?
Tatsächlich ist Memcache der Name dieses Projekts, und Memcached ist der Hauptprogrammdateiname auf seiner Serverseite. Sie wissen, was ich meine. Einer ist der Projektname und der andere der Hauptprogrammdateiname. Ich habe es online gesehen, dass viele Leute es nicht verstehen, also habe ich es gemischt.
Memcached ist ein hochleistungsfähiges, verteiltes Speicherobjekt-Caching-System, das zur Reduzierung der Datenbanklast und zur Verbesserung der Zugriffsgeschwindigkeit in dynamischen Anwendungen verwendet wird. Memcached wurde von Danga Interactive entwickelt, um den Zugang zu LiveJournal.com zu verbessern. LJ hat Tausende von dynamischen Seitenbesuchen pro Sekunde und 7 Millionen Benutzer. Memcached reduziert die Datenbanklast erheblich, zuteilt besser Ressourcen und einen schnelleren Zugriff.
Dieser Artikel behandelt Folgendes:
Memcache
Memcache ist ein in den Memory-Schlüsselwert für kleine Stücke willkürlicher Daten (Zeichenfolgen, Objekte) aus Ergebnissen von Datenbankkunden, API-Aufrufen oder Seitenwiederherstellungen.
Das heißt, die In-Memory-Cache-Datenbank, die eine Schlüsselwert-Paardatenbank ist. Die Datenbank existiert, um die von anderen Diensten im Speicher erhaltenen Daten vorübergehend zu speichern, und kann bei wiederholten Zugriffen direkt aus dem Hit -Cache zurückgegeben werden. Dies beschleunigt nicht nur die Zugriffsraten, sondern reduziert auch die Last für andere Dienste. Hier wird eine einzelne Serverversion von Memcache implementiert und unterstützt gleichzeitige Verbindungen zwischen mehreren Clients.
Der Client stellt eine Telnet -Verbindung mit dem Server her und interagiert dann mit dem Server -Cache gemäß dem Memcache -Protokoll. Die hier implementierten Anweisungen sind GET, SET und DEL. Schauen wir uns das Format jeder Anweisung an
Satz
Set ist eine Speicheranweisung. Geben Sie beim Speichern der Eigenschaften des Befehls grundlegende Informationen in der ersten Zeile ein und geben Sie ihren entsprechenden Wert in der zweiten Zeile ein.
setzen
<wert>/r/n
Wenn der Speicher erfolgreich ist, wird gespeichert, und wenn die Anweisung das Noreply -Attribut enthält, gibt der Server die Informationen nicht zurück.
Der Inhalt jeder Domäne in dieser Richtlinie lautet wie folgt:
Wenn die Anweisung die Kriterien nicht erfüllt, gibt der Server Fehler zurück.
erhalten
Get ist ein Antragsteller, und die Eigenschaften dieses Befehls sind wie folgt:
Holen Sie sich <schlüssel>*/r/n
Es unterstützt die Übergabe von Werten mehrerer Schlüssel. Wenn der Cache einen oder mehrere Schlüssel trifft, werden die entsprechenden Daten zurückgegeben und endet mit dem Ende. Wenn kein Treffer vorgenommen wird, enthält die zurückgegebene Nachricht nicht den Wert, der dem Schlüssel entspricht. Das Format lautet wie folgt:
Wert <Key> <flags> <Byte>/r/n <Datenblocks>/r/nValue <Key> <flags> <Bytes>/r/n <Datenblocks>/r/nenddel
Löschen Sie den Befehl, das Format des Befehls lautet wie folgt:
Del <Key> [Noreply]/r/n
Wenn die Löschung erfolgreich ist, wird gelöscht/r/n zurückgegeben, andernfalls wird nicht_found zurückgegeben. Wenn es einen Noreply -Parameter gibt, gibt der Server keine Antwort zurück.
Java -Sockel
Alles, was Java Socket wissen muss, ist TCP -Protokoll, Sockets und IO -Streams. Ich werde hier nicht auf Details eingehen. Sie können sich auf meine Artikelreihe beziehen. Es wird auch empfohlen, die Java -Netzwerkprogrammierung zu lesen. Ein Buch.
Code -Implementierung
Mit der Kartenfunktion stimmt hier etwas nicht. Sie können am Ende des Artikels zu meiner Projektadresse gehen, um das Klassendiagramm anzuzeigen.
Hier werden der Anleitungsmodus und der Werksmodus verwendet, um die Entkopplung der Anweisungserstellung und -ausführung zu implementieren. Die Befehlsfabrik empfängt die Befehlszeile und gibt eine Befehlsinstanz zurück. Jeder Befehl verfügt über eine Ausführungsmethode, um seine eigenen einzigartigen Operationen auszuführen. Hier wird nur die besondere Implementierung der DEL -Anweisung veröffentlicht.
/** * Verschiedene Anweisungen * Derzeit unterstützt GET, Set, Löschen * * und benutzerdefinierte * Fehler, Ende */public interface -Befehl {/** * Befehl ausführen * @param reader * @param writer */void execute (Reader -Leser, Schriftstellerautor); / *** den Befehlstyp erhalten* @return*/ commandtype GettType ();} /*** einzelne Instanz der Richtlinienfabrik*/öffentliche Klasse CommandFactory {private static CommandFactory factoryFactory; privates statisches Cache <Itelement> memcache; private commandfactory () {} public static CommandFactory getInstance (cache <item> cache) {if (commandfactory == null) {commandfactory = new CommandFactory (); memcache = cache; } return CommandFactory; } / ** * Befehl nach dem Typ der Anweisung * @param commandline * @return * / public -GetCommand (String -Befehlszeile) {if (commandline.matches ("^set. * $")) {Return New setCommand (commandline, memcache); } else if (commandline.matches ("^get.*$")) {return New getCommand (commandline, memcache); } else if (commandline.matches ("^del.*$")) {return New DeleteCommand (commandline, memcache); } else if (commandline.matches ("^end $")) {return New EndCommand (commandline); } else {neuer Fehlercommand zurückgeben (commandline, errorCommand.errortype.Error); }}} /*** Cache -Anweisung löschen*/öffentliche Klasse DeleteCommand Implements Command {private endgültige String -Befehl; privates Final Cache <Item> Cache; privater Stringschlüssel; privat booleschen nory; public deleteCommand (endgültiger String -Befehl, endgültiger Cache <element> cache) {this.command = Befehl; this.cache = cache; initcommand (); } private void initcommand () {if (this.command.contains ("noreply")) {noreply = true; } String [] info = command.split (""); Key = Info [1]; } @Override public void execute (Readerleser, Schriftsteller) {BufferedWriter bfw = (bufferedWriter) Writer; Item item = cache.delete (Schlüssel); if (! noreply) {try {if (item == null) {bfw.write ("not_found/r/n"); } else {bfw.write ("deleted/r/n"); } bfw.flush (); } catch (ioException e) {try {bfw.write ("error/r/n"); bfw.flush (); } catch (ioException e1) {e1.printstacktrace (); } e.printstacktrace (); }}} @Override public commandType GetType () {return commandType.search; }}Implementieren Sie dann den Speicherserver. Um die erste Funktion zu unterstützen, wird LinkedTreemap als zugrunde liegende Implementierung verwendet, und die REMORDEST-Methode wird neu geschrieben. Gleichzeitig wird der CacheManager -Hintergrund -Thread auch verwendet, um abgelaufene Cache -Einträge rechtzeitig zu löschen.
public class memcache implementiert cache <element> {private logger logger = logger.getLogger (memcache.class.getName ()); // LinkedHasMap verwenden, um LRU Private static LinkedHasMasMap <String, Element> Cache zu implementieren; private endgültige int maxsize; // Ladefaktor private endgültige Float default_load_factor = 0,75F; public memcache (endgültig int maxSize) {this.maxSize = maxSize; // Stellen Sie sicher, dass Cache nicht automatisch erweitert wird, nachdem maxSize int CAPAPLE = (int) math.ceil (maxSize /default_load_factor) + 1 erreicht ist. this.cache = new LinkedHasMap <String, Element> (Kapazität, default_load_factor, true) {@Override Protected boolean remeeldErdEnry (map.Entry <String, Element> Eldest) {if (size ()> Maxsize) {logger.info ("Die Cache -Nummer hat die obere Limit und die mindestens die Verwendung von Deleted"). } return size ()> maxSize; }}; // Synchronisierte Zugriffssammlungen implementieren. SynchronizedMap (Cache); } public synchronisierte boolean isfifl () {return cache.size ()> = maxSize; } @Override public item get (String -Schlüssel) {item item = cache.get (key); if (item == null) {logger.info ("Schlüssel in Cache:" + key + "nicht existieren"); null zurückkehren; } else if (item! cache.remove (Schlüssel); null zurückkehren; } logger.info ("Taste aus Cache lesen:" + key + "value:" + item.getValue () + "verbleibende gültige Zeit" + item.Remaintime ()); Gegenstand zurückgeben; } @Override public void set (String -Schlüssel, Elementwert) {logger.info ("Schlüssel zu Cache schreiben:" + yle + "Wert:" + Wert); Cache.put (Schlüssel, Wert); } @Override public item löschen (String -Taste) {logger.info ("Taste aus Cache löschen:" + Key); cache.remove (Schlüssel) zurückgeben; } @Override public int size () {return cache.size (); } @Override public int capacity () {return maxSize; } @Override public iterator <map.Entry <String, Element >> iterator () {return cache.enterrySet (). Iterator (); }} /*** Cache -Manager* Hintergrund -Thread* abgelaufener Cache im Cache löschen*/öffentliche Klasse CACHEMANAGER IPPRAUTS RUNNABLABLE {private logger logger = logger.getLogger (cacheManager.class.getName ()); // Cache Public Cache <Item> Cache; public CacheManager (cache <element> cache) {this.cache = cache; } @Override public void run () {while (true) {iterator <map.Entry <String, Element >> itemiterator = cache.iterator (); while (itemiterator.hasnext ()) {map.Entry <String, Element> Eintrag = itemiterator.next (); Item item = Eintrag.getValue (); if (item.isexpired ()) {logger.info ("Schlüssel:" + einsteiger.getKey () + "Wert" + item.getValue () + "Abgelaufen, aus der Datenbank gelöscht"); itemiterator.remove (); }} try {// Führen Sie das Hintergrundprogramm alle 5 Sekunden TimeUnit.seconds.sleep (5) aus; } catch (interruptedException e) {e.printstacktrace (); }}}}Implementieren Sie schließlich einen Multi-Thread-Socket-Server, auf dem das Serversocket an eine Schnittstelle gebunden ist und den akzeptierten Socket zur Verarbeitung an einen zusätzlichen Thread übergeben.
/*** Server*/öffentliche Klasse iOserver implementiert Server {private boolean stop; // Portnummer Private Final Int Port; // Server Thread Private ServerSocket ServerSocket; private final logger logger = logger.getLogger (ioServer.class.getName ()); // Threadpool, Thread -Kapazität ist MaxConnection Private Final ExecutorService ExecutorService; privates Final Cache <Item> Cache; public ioServer (int port, int maxConnection, cache <element> cache) {if (maxConnection <= 0) Wirf eine neue IllegalArgumentException ("Die maximale Anzahl unterstützter Verbindungen muss eine positive Zahl sein"); this.port = port; ExecutorService = Executors.NewFixedThreadpool (MaxConnection); this.cache = cache; } @Override public void start () {try {serverSocket = new ServerSocket (Port); logger.info ("Der Server startet auf Port"+port+"); while (true) {try {socket socket = serversocket.accept (); logger.info (" erhielt eine Verbindung von "+socket e.PrintStackTrace (); ! /*** Behandle die Verbindungen jedes Clients* Schließen Sie die Verbindung, nachdem Sie die Endanweisung erhalten haben. private Finale Socket Socket; privates Final Cache <Item> Cache; privates boolescher Finish; public sockhandler (Socket s, cache <element> cache) {this.socket = s; this.cache = cache; } @Override public void run () {try {// Socket Input Stream Final BufferedReader Reader = New BufferedReader (neuer InputStreamReader (socket.getInputStream ())); // Socket Output Stream Final BufferedWriter Writer = New BufferedWriter (New OutputStreamWriter (Socket.GetOutputStream ())) erhalten; Commandfactory factoryFactory = commandfactory.getInstance (Cache); while (! finish) {Final String commandline = reader.readline (); logger.info ("ip:" + socket.getLocalAddress () + "Richtlinie:" + commandline); if (commandline == null || commandline.trim (). isEmpty ()) {Fortsetzung; } // Verwenden Sie die Befehlsfabrik, um die Befehlsinstanz -Befehlsbefehlsbefehlsbefehlsbefehlsfunktion zu erhalten. command.execute (Leser, Schriftsteller); if (command.gettType () == commandType.end) {logger.info ("Anfrage zum Schließen der Verbindung"); Finish = wahr; }}} catch (ioException e) {e.printstacktrace (); logger.info ("Die Verbindung von" + socket.getLocalAddress () + ""); } endlich {try {if (socket! = null) {socket.close (); }} catch (ioException e) {e.printstacktrace (); }}}}Bitte klicken Sie hier für die Projektadresse. Wenn Sie denken, dass es ziemlich gut ist, hoffe ich, dass Sie mir einen Stern geben können.
Referenzen
Memcached Offizielle Website
Memcache -Protokoll
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.