Java Schnelle Datenspeicherung und Abfrage

8

Ich muss Datensätze in einem persistenten Speicher speichern und bei Bedarf abrufen. Die Anforderung lautet wie folgt:

  1. Extrem schnelles Abrufen und Einfügen
  2. Jeder Datensatz hat einen eindeutigen Schlüssel. Dieser Schlüssel wird verwendet, um den Datensatz
  3. abzurufen
  4. Die gespeicherten Daten sollten persistent sein, d. h. sollten beim JVM-Neustart verfügbar sein
  5. Ein separater Prozess würde veraltete Datensätze einmal pro Tag in RDBMS verschieben

Was denkt ihr? Ich kann die Standarddatenbank aufgrund von Latenzproblemen nicht verwenden. Speicherdatenbanken wie HSQLDB / H2 haben Leistungseinschränkungen. Außerdem sind die Datensätze einfache String-Objekte und nicht für SQL geeignet. Ich denke an eine Art Flat-File-basierte Lösung. Irgendwelche Ideen? Irgendein Open-Source-Projekt? Ich bin sicher, es muss jemanden geben, der dieses Problem schon einmal gelöst hat.

    
AAK 15.10.2009, 14:01
quelle

15 Antworten

7

Es gibt viele verschiedene Werkzeuge und Methoden, aber ich denke, dass keine von ihnen alle Anforderungen erfüllen kann.

Bei geringer Latenz können Sie sich nur auf den Datenzugriff im Speicher verlassen - Festplatten sind physisch zu langsam (und auch SSDs). Wenn Daten nicht in den Speicher eines einzelnen Rechners passen, müssen wir unsere Daten auf mehr Knoten verteilen, die genug Speicher summieren.

Für persistency müssen wir unsere Daten schließlich auf die Festplatte schreiben. Angenommen optimale Organisation Dies kann als Hintergrundaktivität ausgeführt werden, ohne die Latenz zu beeinflussen. Bei Zuverlässigkeit (Failover, HA oder was auch immer) können die Plattenoperationen nicht völlig unabhängig von den Zugriffsmethoden sein: Wir müssen auf die Platten warten, wenn wir Daten ändern, damit unsere Operation nicht verschwindet. Parallelität fügt auch etwas Komplexität und Latenz hinzu.

Datenmodell ist hier nicht einschränkend: Die meisten Methoden unterstützen den Zugriff basierend auf einem eindeutigen Schlüssel.

Wir müssen uns entscheiden,

  • wenn Daten in den Speicher einer Maschine passen oder wir verteilte Lösungen finden müssen,
  • Wenn Nebenläufigkeit ein Problem ist oder keine parallelen Operationen vorhanden sind,
  • Wenn die Zuverlässigkeit streng ist, können wir keine Änderungen verlieren, oder wir können mit der Tatsache leben, dass ein ungeplanter Absturz zu Datenverlust führen würde.

Lösungen könnten

sein
  • selbst implementierte Datenstrukturen mit Standard-Java-Bibliothek, Dateien usw. sind möglicherweise nicht die beste Lösung, weil Zuverlässigkeit und geringe Latenz clevere Implementierungen und eine Menge Tests erfordern,
  • Traditionelle RDBMS s verfügen über ein flexibles Datenmodell, dauerhafte, atomare und isolierte Operationen, Caching usw. - sie wissen zu viel und sind meist schwer zu verteilen. Deshalb sind sie zu langsam, wenn Sie die unerwünschten Funktionen nicht ausschalten können, was normalerweise der Fall ist.
  • NoSQL und Schlüssel / Wert-Speicher sind gute Alternativen. Diese Begriffe sind ziemlich vage und decken viele Werkzeuge ab. Beispiele sind
    • BerkeleyDB oder Kyoto Cabinet als ein-Maschine persistente Schlüssel-Wert speichert (mit B-Bäumen): kann verwendet werden, wenn der Datensatz klein genug ist, um in den Speicher eines Rechners zu passen.
    • Projekt Voldemort als verteilter Schlüsselwertspeicher: verwendet BerkeleyDB java edition intern, einfach und verteilt,
    • ScalienDB als verteilter Schlüssel / Wert-Speicher: zuverlässig, aber nicht zu langsam für Schreibvorgänge.
    • MemcacheDB, Redis Andere Caching-Datenbanken mit Persistenz,
    • beliebte NoSQL-Systeme wie Cassandra, CouchDB, HBase usw.: hauptsächlich für große Datenmengen verwendet.

Eine Liste von NoSQL-Tools finden Sie z. hier .

Voldemorts Leistungstests melden Antwortzeiten von unter einer Millisekunde, und diese können relativ einfach erreicht werden, wie auch immer wir es tun müssen Vorsicht auch mit der Hardware (wie die oben genannten Netzwerkeigenschaften).

    
csaba 14.07.2011 15:37
quelle
5

Sehen Sie sich Voldemort von LinkedIn an .

    
fvu 15.10.2009 14:31
quelle
4

Wenn alle Daten in den Speicher passen, kann MySQL im Speicher statt auf der Festplatte ausgeführt werden (MySQL Cluster, Hybrid Storage). Es kann dann behandeln, sich für Sie auf Festplatte zu speichern.

    
Dean J 15.10.2009 14:34
quelle
4

Was ist mit etwas wie CouchDB ?

    
Mark 15.10.2009 15:20
quelle
3

Ich würde dafür eine BlockingQueue verwenden. Einfach und in Java integriert .
Ich mache etwas ähnliches mit Echtzeitdaten von Chicago Merchantile Exchange.
Die Daten werden zur Echtzeitnutzung an einen Ort gesendet ... und an einen anderen Ort (über TCP), Verwenden einer BlockingQueue (Producer / Consumer), um die Daten in einer Datenbank (Oracle, H2) persistent zu speichern.
Der Consumer verwendet ein zeitverzögertes Commit , um fdisk-Synchronisierungsprobleme in der Datenbank zu vermeiden. (Datenbanken vom Typ H2 sind standardmäßig asynchrone Commits und vermeiden dieses Problem) Ich protokolliere die persistierende in der Consumer, um die Warteschlangengröße zu verfolgen, um sicher zu sein es ist in der Lage, mit dem Produzenten Schritt zu halten. Funktioniert ziemlich gut für mich.

    
Richard L Faber 27.02.2012 18:35
quelle
2

MySQL mit Shards kann eine gute Idee sein. Es hängt jedoch davon ab, was für Datenvolumen, Transaktionen pro Sekunde und Latenz Sie benötigen.

In Speicher-Datenbanken sind auch eine gute Idee. Tatsächlich bietet MySQL auch speicherbasierte Tabellen.

    
Shantanu Kumar 15.10.2009 14:10
quelle
2

Würde ein Tuple-Space / JavaSpace funktionieren? Überprüfen Sie auch andere Unternehmensdatenstrukturen wie Oracle Coherence und Edelstein .

    
Kevin 15.10.2009 15:03
quelle
1

Haben Sie tatsächlich bewiesen, dass die Verwendung einer Out-of-Process-SQL-Datenbank wie MySQL oder SQL Server zu langsam ist, oder ist dies eine Annahme?

Sie können einen SQL-Datenbankansatz in Verbindung mit einem speicherinternen Cache verwenden, um sicherzustellen, dass Abrufvorgänge überhaupt nicht auf die Datenbank treffen. Trotz der Tatsache, dass die Datensätze Klartext sind, würde ich immer noch empfehlen, SQL über eine Flatfilelösung zu verwenden (zB eine Textspalte in Ihrem Tabellenschema), da das RDBMS Optimierungen durchführt, die ein Dateisystem nicht durchführen kann (zB Zwischenspeichern kürzlich aufgerufener Seiten, etc.) .

Ohne weitere Informationen über Ihre Zugriffsmuster, den erwarteten Durchsatz usw. kann ich jedoch nicht viel mehr Vorschläge machen.

    
Adamski 15.10.2009 14:12
quelle
1

Wenn Sie nach einem einfachen Schlüssel / Wert-Speicher suchen und keine komplexe SQL-Abfrage benötigen, Berkeley DB könnte einen Blick wert sein.

Eine andere Alternative ist Tokyo Cabinet , eine moderne DBM-Implementierung.

    
Peter Hoffmann 15.10.2009 14:48
quelle
1

Wie schlimm wäre es, wenn Sie im Falle eines Absturzes ein paar Einträge verlieren würden?

Wenn es nicht so schlimm ist, könnte der folgende Ansatz für Sie funktionieren:

Erstellen Sie flache Dateien für jeden Eintrag, der Name der Datei entspricht der ID. Mögliche eine Datei für eine nicht so große Anzahl von aufeinanderfolgenden Einträgen.

Stellen Sie sicher, dass Ihr Controller über einen guten Cache verfügt und / oder verwenden Sie einen der vorhandenen Caches, die in Java implementiert sind.

Sprechen Sie mit einem Dateisystemexperten, wie Sie das wirklich schnell machen können

Es ist einfach und es könnte schnell sein. Natürlich verlieren Sie Transaktionen einschließlich der ACID-Prinzipien.

    
Jens Schauder 15.10.2009 14:33
quelle
1

Eine Untermillisekunde bedeutet, dass Sie nicht auf die Festplatte angewiesen sind, und Sie müssen auf die Netzwerklatenz achten. Vergessen Sie einfach Standard-SQL-basierte Lösungen, Hauptspeicher oder nicht. In einer ms können Sie nicht mehr als 100 KByte über ein GBit-Netzwerk erhalten. Fragen Sie einen Telekommunikationsingenieur, sie sind es gewohnt, diese Art von Problemen zu lösen.

    
Stephan Eggermont 21.10.2009 12:34
quelle
1

Wie wichtig ist es, wenn Sie ein oder zwei Datensätze verlieren? Woher kommen sie? Haben Sie eine Transaktionsbeziehung mit der Quelle?

Wenn Sie ernsthafte Zuverlässigkeitsanforderungen haben, dann müssen Sie möglicherweise bereit sein, etwas DB Overhead zu bezahlen.

Vielleicht könnten Sie das Persistenzproblem vom In-Memory-Problem trennen. Verwenden Sie einen Welpen-Sub-Ansatz. Ein Teilnehmer kümmert sich im Speicher, der andere hält die Daten für den nächsten Start bereit?

Verteilte Cahcing-Produkte, wie z. B. WebSphere eXtreme Scale (keine Java EE-Abhängigkeit) Relevant, wenn Sie kaufen können, anstatt zu bauen.

    
djna 15.10.2009 14:14
quelle
0

MapDB bietet hochperformante HashMaps / TreeMaps, die auf der Festplatte gespeichert werden. Es ist eine einzelne Bibliothek, die Sie in Ihr Java-Programm einbetten können.

    
Andrejs 19.12.2013 19:54
quelle
0

Chronik-Map ist eine ConcurrentMap -Implementierung, die Schlüssel und Werte außerhalb des Heapspeichers in einer Memory-Mapped-Datei speichert . Sie haben also eine Persistenz beim JVM-Neustart.

ChronicleMap.get() ist konsistent schneller als 1 us, manchmal so schnell wie 100 ns / operation. Es ist die schnellste Lösung in der Klasse.

    
leventov 18.03.2017 22:57
quelle
-1

Passen alle Datensätze und Schlüssel, die Sie benötigen, gleichzeitig in den Speicher? Wenn ja, könnten Sie einfach eine HashMap & lt; String, String & gt; verwenden, da diese serialisierbar ist.

    
wdebeaum 15.10.2009 14:13
quelle

Tags und Links