[GO] Hinweise zu Transaktionen in der Java-Clientbibliothek im Datenspeicher

Hintergrund:

Verwenden der Java-Clientbibliothek (Google Cloud-Clientbibliothek für Java) zur Verwendung des Datenspeichers Es gibt. Ich habe untersucht, wie diese Transaktion in der Multithread-Verarbeitung funktioniert. Das offizielle Dokument hatte die folgende Spezifikationserklärung, daher habe ich es beim Ausführen des Codes überprüft.

Wenn für eine oder mehrere allgemeine Entitätsgruppen mehrere Transaktionen gleichzeitig versuchen, eine Entität zu ändern, ist nur die erste Transaktion erfolgreich, die die Änderung festschreibt, und alle anderen Transaktionen können nicht festgeschrieben werden. Werden.

Wir haben auch bestätigt, was passiert, wenn die Verarbeitung über das Transaktionsobjekt und die Verarbeitung über das Datenspeicherobjekt gemischt werden.

Dokumentation Dokumente zu Transaktionen

Was ich getan habe

Überprüfen Sie, was passiert, wenn Sie in den folgenden drei Fällen versuchen, eine Entität aus mehreren Threads zu aktualisieren

Szenario 1

Holen Sie sich die Entität von Thread1 über Transaktion und Ruhezustand -> Entität von Thread2 über Transaktion & Update abrufen -> Update über Transaktion mit Thread1

Szenario 2

Holen Sie sich die Entität von Thread1 über Transaktion und Ruhezustand -> Entität von Thread2 über Datenspeicher & Update abrufen -> Update über Transaktion mit Thread1

Szenario 3

Holen Sie sich die Entität von Thread1 über den Datenspeicher und schlafen Sie -> Entität von Thread2 über Transaktion & Update abrufen -> Update über Datenspeicher mit Thread1

Fazit

Aktualisieren Sie im Fall von transaction.update, nachdem Sie bestätigt haben, ob sich die Entität zum Zeitpunkt des Erwerbs geändert hat. Die Ausnahme ist, wenn sich der Status der Entität geändert hat. Es spielt keine Rolle, ob der Aktualisierungsprozess über ein Transaktionsobjekt oder ein Datenspeicherobjekt erfolgt.

Bestätigungscode

Szenario 1

Code


package jp.ne.opt.spinapp.runner;

import com.google.cloud.datastore.*;

public final class DatastoreTest {
    final static String NAME_SPACE = "dataflow";
    final static String LOCK_KIND = "lock";
    final static String LOCK_PROP_VALUE = "value";
    final static Datastore DATASTORE = DatastoreOptions.getDefaultInstance().getService();
    final static KeyFactory KEY_FACTORY = DATASTORE.newKeyFactory().setNamespace(NAME_SPACE).setKind(LOCK_KIND);
    final static Transaction TRANSACTION = DATASTORE.newTransaction();

    public static void main(final String[] args) throws InterruptedException {
        MultiThread1 mt1 = new MultiThread1();
        MultiThread2 mt2 = new MultiThread2();
        mt1.start();
        Thread.sleep(1000);
        mt2.start();
    }
}

class MultiThread1 extends Thread {
    public void run() {
        Entity lock = DatastoreTest.TRANSACTION.get(DatastoreTest.KEY_FACTORY.newKey("test"));
        System.out.println("got lock from 1: " + lock.getLong((DatastoreTest.LOCK_PROP_VALUE)));
        try {
            Thread.sleep(3000);
            System.out.println("sleep 1 ended");
            Entity entity = Entity.newBuilder(lock).set(DatastoreTest.LOCK_PROP_VALUE, 1).build();
            DatastoreTest.TRANSACTION.update(entity);
            DatastoreTest.TRANSACTION.commit();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (DatastoreTest.TRANSACTION.isActive()) {
                DatastoreTest.TRANSACTION.rollback();
            }
        }
        System.out.println("thread1 done.");
    }
}

class MultiThread2 extends Thread {
    public void run() {
        Entity lock = DatastoreTest.TRANSACTION.get(DatastoreTest.KEY_FACTORY.newKey("test"));
        System.out.println("got lock from 2: " + lock.getLong((DatastoreTest.LOCK_PROP_VALUE)));
        try {
            Entity entity = Entity.newBuilder(lock).set(DatastoreTest.LOCK_PROP_VALUE, 2).build();
            DatastoreTest.TRANSACTION.update(entity);
            DatastoreTest.TRANSACTION.commit();
        } finally {
            if (DatastoreTest.TRANSACTION.isActive()) {
                DatastoreTest.TRANSACTION.rollback();
            }
        }
        System.out.println("thread2 done.");
    }
}
got lock from 2: 0
got lock from 1: 0
thread2 done.
sleep 1 ended
[WARNING]
com.google.cloud.datastore.DatastoreException: transaction is no longer active

Nach dem Festschreiben von Thread2 wird beim Versuch, ein Update auf Thread1 durchzuführen, eine Transaktion nicht mehr aktiv. Der Datenspeicher wird mit Thread2 aktualisiert.

Szenario 2


class MultiThread1 extends Thread {
    public void run() {
        Entity lock = DatastoreTest.TRANSACTION.get(DatastoreTest.KEY_FACTORY.newKey("test"));
        System.out.println("got lock from 1: " + lock.getLong((DatastoreTest.LOCK_PROP_VALUE)));
        try {
            Thread.sleep(10000);
            System.out.println("sleep 1 ended");
            Entity entity = Entity.newBuilder(lock).set(DatastoreTest.LOCK_PROP_VALUE, 1).build();
            DatastoreTest.TRANSACTION.update(entity);
            DatastoreTest.TRANSACTION.commit();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (DatastoreTest.TRANSACTION.isActive()) {
                DatastoreTest.TRANSACTION.rollback();
            }
        }
        System.out.println("thread1 done.");
    }
}

class MultiThread2 extends Thread {
    public void run() {
        Entity lock = DatastoreTest.DATASTORE.get(DatastoreTest.KEY_FACTORY.newKey("test"));
        System.out.println("got lock from 2: " + lock.getLong((DatastoreTest.LOCK_PROP_VALUE)));
        Entity entity = Entity.newBuilder(lock).set(DatastoreTest.LOCK_PROP_VALUE, 2).build();
        DatastoreTest.DATASTORE.update(entity);
        System.out.println("thread2 done.");
    }
}
got lock from 1: 0
got lock from 2: 0
thread2 done.
sleep 1 ended
[WARNING]
com.google.cloud.datastore.DatastoreException: too much contention on these datastore entities. please try again. entity groups: [(app=b~spinapptest-151310!dataflow, lock, "test")]

Nach dem Update mit Thread2 tritt ein Fehler beim Aktualisieren mit Thread1 auf. Der Datenspeicher wird mit Thread2 aktualisiert.

Szenario 3


class MultiThread1 extends Thread {
    public void run() {
        try {
            Entity lock = DatastoreTest.DATASTORE.get(DatastoreTest.KEY_FACTORY.newKey("test"));
            Thread.sleep(10000);
            System.out.println("sleep 1 ended");
            System.out.println("got lock from 1: " + lock.getLong((DatastoreTest.LOCK_PROP_VALUE)));
            Entity entity = Entity.newBuilder(lock).set(DatastoreTest.LOCK_PROP_VALUE, 1).build();
            DatastoreTest.DATASTORE.update(entity);
            System.out.println("thread1 done.");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class MultiThread2 extends Thread {
    public void run() {
        Entity lock = DatastoreTest.TRANSACTION.get(DatastoreTest.KEY_FACTORY.newKey("test"));
        System.out.println("got lock from 2: " + lock.getLong((DatastoreTest.LOCK_PROP_VALUE)));
        try {
            Entity entity = Entity.newBuilder(lock).set(DatastoreTest.LOCK_PROP_VALUE, 2).build();
            DatastoreTest.TRANSACTION.update(entity);
            DatastoreTest.TRANSACTION.commit();
        } finally {
            if (DatastoreTest.TRANSACTION.isActive()) {
                DatastoreTest.TRANSACTION.rollback();
            }
        }
        System.out.println("thread2 done.");
    }
}
got lock from 2: 0
thread2 done.
sleep 1 ended
got lock from 1: 0
thread1 done.

Beide Thread-Prozesse sind erfolgreich.

Recommended Posts

Hinweise zu Transaktionen in der Java-Clientbibliothek im Datenspeicher
Hinweise zur Verwendung von Marshmallow in der Schemabibliothek
Hinweise zu imshow () von OpenCV
Hinweise zur Farbfärbung im Matplotlib-Streudiagramm
Hinweise zur Verwendung von matplotlib auf dem Server
Hinweise zur Installation von Ubuntu 18.04 auf XPS 15 7590
Versuchen Sie, eine E-Mail mit der Google Mail API-Clientbibliothek für Java zu senden
Anmerkung von nfc.ContactlessFrontend () von nfcpy von Python
Hinweise zum Erstellen statischer Dateien mit Django
Implementieren Sie OAuth ohne Client-Bibliothek (Java)
Was ist "Mahjong" in der Python-Bibliothek? ??
Rückblick auf 2016 in der Crystal-Sprache
SELECT-Daten mithilfe der Client-Bibliothek mit BigQuery
Verwendung der C-Bibliothek in Python
Führen Sie Aufgaben im Hintergrund auf dem Server aus, an den Sie gesendet haben
Häufig verwendete (persönliche) Notizen für den Befehl tar
Twitter-Streaming-Client zum Genießen im Terminal
Hinweise zur Verwendung von dict mit Python [Competition Pro]
ABC125_C --GCD auf Blackboard [In Python gelöste Notizen]
Verwenden Sie die LibreOffice-App in Python (3) Bibliothek hinzufügen
Installieren Sie die Bibliothek für maschinelles Lernen TensorFlow auf fedora23
Ein Hinweis zur Bibliotheksimplementierung, in der Hyperparameter mithilfe der Bayes'schen Optimierung in Python untersucht werden