"Journaling" oder "Transaktionen" Designmuster? [geschlossen]

8

Ich möchte ein Objekt implementieren, das im Journal gespeichert ist oder in dem eine persistente Transaktion enthalten ist. Das heißt, das Objekt enthält Daten (möglicherweise eine Map). Wenn Änderungen an den Daten vorgenommen werden, werden diese Änderungen separat gespeichert, wenn Sie möchten, so dass jedes externe Objekt entweder auf den Basiszustand verweisen kann (vor den Änderungen) oder auf die neuesten Daten zugreifen kann. Dann gibt es eine andere Operation, die die Änderungen in den Basiszustand überträgt.

Es erinnert mich etwas an das Linux-Journaling-Dateisystem. Dateisystemänderungen werden in ein Journal geschrieben und erst später in den permanenten Speicher übernommen.

Es ist vielleicht auch dem Konzept einer "Transaktion" in der relationalen Datenbankwelt ähnlicher; das heißt, Sie haben einige Daten, Sie beginnen eine Transaktion und manipulieren die Daten in irgendeiner Weise. Gleichzeitige Prozesse sehen die alten Daten mit keiner Ihrer Änderungen. Dann können Sie entweder die Transaktion "zurücksetzen" oder Ihre Änderungen "festschreiben".

Ich versuche speziell, dies in Java zu implementieren, aber offensichtlich ist es ein allgemeines objektorientiertes Muster, falls es überhaupt existiert. Ich hoffe, dass es zumindest erstellt werden kann, aber ich bin mir nicht sicher, wie es am besten umgesetzt werden kann.

Nehmen Sie außerdem an, dass das Objekt eine ganze Tonne Daten enthält, eine ganze Hierarchie (Unterobjekte usw.). Man kann also nicht einfach zwei Kopien des gesamten Datenbaums behalten; es wäre sehr speicherverschwendend und die Kopieroperation (beim Festschreiben) würde viel zu lange dauern. Ich versuche, dies im Kontext eines Spiels zu implementieren, mit einer Commit-Operation pro Frame, also muss es wirklich optimal sein.

    
Ricket 29.07.2010, 05:11
quelle

4 Antworten

7

Der beste Weg, um das zu erreichen, was Sie wollen, ist, das Objekt und alle seine Unterobjekte unveränderlich zu machen. Dann können die beiden Threads ohne Konflikte mit ihnen arbeiten, und Sie müssen nicht zwei Kopien von allem verwalten. Die einzigen Dinge, die zwei Kopien erfordern, sind die Dinge, die sich tatsächlich ändern, und diese können sehr klein sein.

Angenommen, das Objekt A besteht aus den Objekten B und C. Das Objekt B besteht aus den Objekten D und E. Und das Objekt C besteht aus den Objekten F und G. Also sind A, B und C jeweils nur zwei Zeiger und D , E, F und G sind was auch immer sie sind.

Zuerst erstellen Sie Ihre erste Instanz und geben sie beiden Threads.

%Vor%

Beide Threads zeigen also auf die gleiche Instanz, es wird kein zusätzlicher Speicher verbraucht und es gibt keine Threading-Probleme, da sich die Objekte niemals ändern.

Nun muss ThreadOne das Objekt F modifizieren. Dazu erstellt es einfach ein neues F, ein neues C, um es zu enthalten, und ein neues A, um das neue C zu enthalten. Die ursprünglichen B, D, E und G sind unverändert und muss nicht kopiert werden.

%Vor%

Die beiden Threads teilen sich die Instanzen von B, D, E und G.

Nun muss ThreadOne das Objekt E ändern.

%Vor%

Nun benötigt ThreadTwo die neueste Version, daher gibt ThreadOne nur einen Zeiger auf seine Kopie.

%Vor%

Da die Objekte unveränderlich sind, besteht keine Gefahr von Threading-Problemen, und ThreadOne kann sofort Änderungen vornehmen und jedes Mal eine neue Instanz nur der geänderten Teile und ihrer Container erstellen.

%Vor%

Dies ist schnell, speichereffizient und threadsicher.

    
Jeffrey L Whitledge 29.07.2010, 17:09
quelle
1

Was Sie suchen, ist das Befehlsmuster . Sie erstellen Befehlsobjekte, die die Änderungen ausführen und rückgängig machen, speichern nur einen Basiszustand und geben dann alle Befehle wieder, die erforderlich sind, um das Objekt in den gewünschten Zustand zu versetzen.

    
Jarrod Roberson 29.07.2010 05:20
quelle
1

Was du beschreibst, klingt sehr nach dem Memento-Muster . Sie haben jedoch angegeben, dass Sie den gesamten Status des Objekts nicht speichern möchten, sodass das Muster möglicherweise nicht für Sie "out-of-the-box" funktioniert.

Sie können es jedoch möglicherweise so ändern, dass das Memento nur die Deltas und nicht den vollständigen Objektstatus enthält. Dies würde zu einem geringeren Speicherbedarf führen. Es würde aber auch bedeuten, dass Sie die Zustände nur in der Reihenfolge zurücksetzen können, da ihre Deltas aufeinander aufbauen würden.

    
mikemanne 30.07.2010 20:21
quelle
1

Sie können die Befehls- und Memento-Muster koppeln. Sie können über konkrete Befehle verfügen, die die Commit- und Rollback-Vorgänge und -Mentos implementieren, die den Status des geänderten Objekts vor dem Festschreiben speichern.

    
Daniel Voina 03.08.2010 18:43
quelle