Frage

Ich brauche Transaktionen zu tun (beginnen, Commit oder Rollback), Schlösser (wählen Sie für die Aktualisierung). Wie kann ich es tun in einem Dokumentmodell db?

Edit:

Der Fall ist dies:

  • Ich möchte eine Auktion Website starten.
  • Und ich denke, wie Kauf zu lenken als auch.
  • In einem direkten Kauf ich das Mengenfeld in dem Positionssatz zu verringern, aber nur dann, wenn die Menge größer als Null ist. Deshalb habe ich Schlösser und Transaktionen müssen.
  • Ich weiß nicht, wie das adressieren, ohne Schleusen und / oder Transaktionen.

Kann ich das mit CouchDB lösen?

War es hilfreich?

Lösung

Nein. CouchDB verwendet eine „Parallelität“ -Modell. In einfachen Worten ausgedrückt, bedeutet dies nur, dass Sie eine Dokumentversion zusammen mit Ihrem Update senden, und CouchDB lehnt die Änderung, wenn die aktuelle Version des Dokuments, was Sie bisher nicht übereinstimmt gesendet.

Es ist trügerisch einfach, wirklich. Sie können viele normale transaktionsbasierte Szenarien für CouchDB reframe. Sie müssen irgendwie zu Ihrem RDBMS Domänenwissen hinauswerfen, wenn CouchDB Lernen, though. Es ist hilfreich, Probleme von einer höheren Ebene zu nähern, anstatt auf eine SQL-basierten Welt zu formen Couch versucht.

Die Verfolgung von Inventar

Das Problem, das Sie skizziert ist in erster Linie eine Bestands Problem. Wenn Sie ein Dokument haben, ein Element zu beschreiben, und es enthält ein Feld für „Warenbestand“ können Sie Parallelität Fragen wie diese handhaben:

  1. Rufen Sie das Dokument, nehmen die _rev Eigenschaft, die CouchDB entlang
  2. sendet
  3. Decrement das Mengenfeld, wenn es größer als Null
  4. Senden Sie das aktualisierte Dokument zurück, das _rev Eigenschaft mit
  5. Wenn die _rev die aktuell gespeicherten Nummer übereinstimmt, durchgeführt werden!
  6. Wenn es einen Konflikt gibt (wenn _rev nicht übereinstimmt), rufen Sie die neueste Version des Dokuments

In diesem Fall gibt es zwei mögliche Ausfallszenarien zu denken. Wenn die jüngste Version des Dokuments eine Menge von 0, behandeln Sie es mögen nur würden Sie in einem RDBMS und alarmiert den Benutzer, dass sie nicht wirklich kaufen können, was sie kaufen wollten. Wenn die jüngste Version des Dokuments eine Menge größer als 0 hat, wiederholen Sie einfach den Vorgang mit den aktualisierten Daten, und wieder am Anfang beginnen. Dies zwingt Sie ein bisschen mehr Arbeit als ein RDBMS zu tun würde, und könnte ein wenig ärgerlich, wenn es häufig widersprüchliche Updates.

Nun, die Antwort gab ich nur voraussetzt, dass Sie gehen auf die gleiche Weise in vielen Dinge in CouchDB zu tun, dass man es in einem RDBMS. Ich könnte dieses Problem etwas anders angehen:

würde ich mit einem „Master-Produkt“ Dokument starten, die alle Deskriptordatenstruktur enthält (Name, Bild, Beschreibung, Preis, etc). Dann würde ich ein „Bestandskarte“ Dokument für jede bestimmte Instanz, mit Feldern für product_key und claimed_by hinzuzufügen. Wenn Sie ein Modell von Hammer verkaufen, und haben 20 von ihnen zu verkaufen, können Sie Dokumente mit Tasten wie hammer-1 haben, hammer-2, etc, jeden verfügbaren Hammer darzustellen.

Dann würde ich eine Ansicht erstellen, die mir eine Liste der verfügbaren Hämmer, mit einer Verringerung Funktion gibt, die mir ein „total“ lässt sehen. Diese sind vollständig aus dem Stehgreif, aber sollen Sie eine Vorstellung davon, was eine Arbeitsansicht aussehen würde.

Karte

function(doc) 
{ 
    if (doc.type == 'inventory_ticket' && doc.claimed_by == null ) { 
        emit(doc.product_key, { 'inventory_ticket' :doc.id, '_rev' : doc._rev }); 
    } 
}

Das gibt mir eine Liste der verfügbaren „Ticket“, die von dem Produktschlüssel. Ich konnte eine Gruppe von ihnen greifen, wenn jemand einen Hammer kaufen will, dann durchlaufen Updates zu senden (die id und _rev verwenden) bis I (wird in einem Update-Fehler zur Folge haben zuvor behauptet Tickets) erfolgreich ein Anspruch.

reduzieren

function (keys, values, combine) {
    return values.length;
}

Diese reduzieren Funktion gibt einfach die Gesamtzahl der nicht beanspruchten inventory_ticket Elemente, so kann Ihnen sagen, wie viele „Hämmer“ käuflich zu erwerben sind.

Caveats

Diese Lösung entspricht etwa 3,5 Minuten des gesamten Denkens für das jeweilige Problem, das Sie vorgestellt haben. Es können bessere Möglichkeiten, dies zu tun! Das heißt, es wird im Wesentlichen in Konflikt stehenden Updates reduzieren und verkürzt sich auf die Notwendigkeit, zu einem Konflikt mit einem neuen Update zu reagieren. Bei diesem Modell werden Sie nicht mehr Benutzer versuchen, Daten in primärem Produkteintrag zu ändern. Im schlimmsten Fall, haben Sie mehrere Benutzer eine einfache Fahrkarte Anspruch versuchen, und wenn Sie mehrere von denen aus Ihrer Sicht gepackt haben, können Sie einfach zum nächsten Ticket weitergehen und versuchen,wieder.

Referenz: https://wiki.apache.org/couchdb/Frequently_asked_questions#How_do_I_use_transactions_with_CouchDB. 3F

Andere Tipps

Die Erweiterung auf MrKurt Antwort. Für viele Szenarien benötigen Sie keine Lager Tickets, um erlöst zu haben. Anstatt das erste Ticket auswählen, können Sie zufällig aus den verbleibenden Tickets wählen. Bei einer großen Anzahl Tickets und eine große Anzahl von gleichzeitigen Anforderungen, werden Sie viel reduziert Streit auf jenen Karten, im Vergleich zu jeder versuchen, das erste Ticket zu erhalten.

Ein Entwurfsmuster für Transaktionen ist eine restfull „Spannung“ im System zu erstellen. Für den beliebten Beispiel Anwendungsfall eines Kontotransaktionsbank müssen Sie sicherstellen, die Summe für beiden beteiligten Konten zu aktualisieren:

  • Erstellen Sie eine Transaktion Dokument „übertragen 10 USD von Konto 11.223-88.733 Konto“. Dies schafft die Spannung im System.
  • Um eine Spannung Scan für alle Transaktionsdokumente zu lösen und
    • Wenn das Quellkonto wird nicht aktualisiert, noch das Quellkonto aktualisieren (-10 USD)
    • Wenn die Quelle Konto aktualisiert wurde, aber die Transaktion Dokument zeigt nicht diese dann die Transaktion Dokument aktualisieren (z gesetzten Flag „sourcedone“ im Dokument)
    • Wenn das Zielkonto wird nicht aktualisiert, noch das Zielkonto aktualisieren (10 USD)
    • Wenn das Zielkonto wurde aktualisiert, aber die Transaktion Dokument zeigt nicht, diese dann die Transaktion Dokument aktualisieren
    • Wenn beide Konten aktualisiert wurden, können die Transaktionsdokument löschen oder halten für die Prüfung.

Die Abtastung für Spannung sollte für alle „tension Dokumente“ in einem Backend-Prozess durchgeführt wird kurz die Zeiten der Spannung im System zu halten. Im obigen Beispiel wird es eine kurze Zeit inconsistence erwartet, wenn das erste Konto wird aktualisiert, aber der zweite ist noch nicht aktualisiert. Dies muss die gleiche Art und Weise berücksichtigt werden Sie mit Eventual Consistency beschäftigen werden, wenn Ihr CouchDB verteilt wird.

Eine weitere mögliche Implementierung vermeidet für Transaktionen die Notwendigkeit vollständig: nur die Spannung Dokumente speichern und den Status Ihres Systems zu bewerten, indem sie jedes beteiligte Spannung Dokument zu bewerten. In dem obigen Beispiel würde dies bedeuten, dass die Summe für ein Konto nur als die Summe in den Transaktionsdokumenten Werte bestimmt wird, in dem dieses Konto beteiligt ist. In CouchDB können Sie dies sehr schön als eine Karte modellieren / reduzieren Ansicht.

Nein, CouchDB für Transaktionsanwendungen im Allgemeinen nicht geeignet ist, weil es nicht atomare Operationen in einer gruppierten / replizierten Umgebung nicht unterstützt.

CouchDB geopfert Transaktionsfähigkeit für Skalierbarkeit. Um atomare Operationen zu haben, benötigen Sie ein zentrales Koordinationssystem, das Ihre Skalierbarkeit begrenzt.

Wenn Sie garantieren Sie nur eine CouchDB Instanz haben oder, dass jeder eine Verbindung zur gleichen CouchDB Instanz eines bestimmtes Dokument zu modifizieren, dann könnten Sie das Konflikt-Detektionssystem verwenden, um eine Art von Unteilbarkeit zu erstellen Methoden oben beschrieben, aber wenn Sie später vergrößern oder zu einem Cluster einen gehosteten Dienst wie Cloudant verwendet es brechen und Sie werden feststellen, dass ein Teil des Systems wiederholen haben.

Also, mein Vorschlag wäre, etwas anderes als CouchDB für Ihre Kontostände zu verwenden, wird es viel einfacher, auf diese Weise sein.

Als Antwort auf das Problem des OP ist Couch wahrscheinlich nicht die beste Wahl hier. Mit Blick ist eine gute Möglichkeit, die Verfolgung von Inventar zu halten, aber auf 0 Spann ist mehr oder weniger unmöglich. Das Problem ist die Race-Bedingung, wenn Sie das Ergebnis einer Ansicht zu lesen, entscheiden Sie ok sind einen „Hammer-1“ Artikel zu verwenden, und dann ein Dokument schreiben, es zu benutzen. Das Problem ist, dass es kein Atom Weg, um nur den doc schreibt den Hammer zu verwenden, wenn das Ergebnis der Ansicht ist, dass es> 0 Hammer-1. Wenn 100 Benutzer alle die Ansicht, die gleichzeitig abzufragen und sehen, 1 Hammer-1, können sie alle schreiben ein doc einen Hammer zu verwenden 1, was zu -99 Hammer-1. In der Praxis wird die Race-Bedingung ziemlich klein sein - wirklich klein, wenn Ihre DB localhost läuft. Aber sobald Sie skalieren und haben eine Off-Site-DB-Server oder Cluster, wird das Problem viel stärker spürbar zu bekommen. Egal, es ist nicht akzeptabel, ein Rennen Zustand dieser Art in einem kritischen zu haben -. Geld bezogenes System

Ein Update auf MrKurt Antwort (es nur datiert werden kann, oder er von einigen CouchDB Funktionen nicht bewusst gewesen sein mag)

Eine Ansicht ist eine gute Möglichkeit, Dinge wie Salden / Vorräte in CouchDB zu behandeln.

Sie brauchen nicht auf die docid und rev in einer Ansicht zu emittieren. Sie erhalten beide von denen kostenlos, wenn Sie Ansicht Ergebnisse abzurufen. Ausstrahlen von ihnen - vor allem in einem ausführlichen Format wie ein Wörterbuch -. Wird nur wachsen Ihre Ansicht nach unnötig groß

Eine einfache Ansicht für Vorratsbestände Tracking sollte wie folgt aussehen (auch aus der Spitze von meinem Kopf)

function( doc )
{
    if( doc.InventoryChange != undefined ) {
        for( product_key in doc.InventoryChange ) {
            emit( product_key, 1 );
        }
    }
}

Und die Funktion reduzieren, ist noch einfacher

_sum

Dieses verwendet einen eingebaute Funktion reduzieren dass nur die Werte aller Zeilen summiert mit passende Schlüssel.

In dieser Ansicht kann jedes Dokument ein Mitglied „InventoryChange“ haben, die PRODUCT_KEY die zu einer Änderung der Gesamtbestand von ihnen zuordnet. dh.

{
    "_id": "abc123",
    "InventoryChange": {
         "hammer_1234": 10,
         "saw_4321": 25
     }
}

Würden 10 hammer_1234 des und 25 saw_4321 ist hinzuzufügen.

{
    "_id": "def456",
    "InventoryChange": {
        "hammer_1234": -5
    }
}

Möchten brennen 5 Hämmer aus dem Inventar.

Mit diesem Modell sind Sie nie irgendwelche Daten zu aktualisieren, nur anhängen. Das bedeutet, es gibt keine Möglichkeit für Update-Konflikte. Alle Transaktions Fragen der Aktualisierung von Daten gehen weg:)

Ein andere nette Sache über dieses Modell ist, dass jedes Dokument in der DB beide hinzufügen und Gegenstände aus dem Inventar subtrahieren. Diese Dokumente können alle Arten von anderen Daten in ihnen. Sie könnten ein „Sendung“ Dokument mit einem Bündel von Daten über das Datum und die Uhrzeit erhielt, Lager, Mitarbeiter usw. zu empfangen und solange die doc eine InventoryChange definiert, wird es das Inventar aktualisieren. Wie könnte ein „Sale“ doc, und ein „DamagedItem“ doc usw. an jedem Dokument Sehen, lesen sie sehr deutlich. Und der Blick kümmert sich um alle die harte Arbeit.

Eigentlich kann man in einer Art und Weise. Werfen Sie einen Blick auf die HTTP Dokument API und scrollen Sie nach unten auf die Überschrift „Ändern Mehrere Dokumente mit einem Single Request“.

Im Grunde können Sie erstellen / aktualisieren / löschen Sie eine Reihe von Dokumenten in einem einzigen Post-Anforderung zu URI / {dbname} / _ bulk_docs und sie werden entweder alle Erfolg haben oder scheitern alle. Das Dokument macht Vorsicht, dass dieses Verhalten in der Zukunft ändern kann, though.

EDIT:. Wie vorhergesagt, von Version 0.9 der Bulk-docs nicht mehr funktioniert auf diese Art und Weise

Verwenden Sie einfach SQlite Art leichte Lösung für Transaktionen und wenn die Transaktion erfolgreich replizieren abgeschlossen ist, und markieren Sie es in SQLite repliziert

SQLite Tabelle

txn_id    , txn_attribute1, txn_attribute2,......,txn_status
dhwdhwu$sg1   x                    y               added/replicated

Sie können auch die Transaktionen löschen, die erfolgreich repliziert werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top