In diesem Artikel geht es um das Erstellen einer Beispiel-App. Lassen Sie uns die Beispiel-App von ScalarDB ausführen.
Klicken Sie hier, um die Umgebung zu erstellen (https://qiita.com/XCAT_SE/private/07969c960fb776d78990).
Für ScalarDB gibt es zwei Betriebskomponenten: die Speicherkomponente und die Transaktionskomponente.
Diese Komponente hat die folgenden Funktionen.
Darüber hinaus entspricht die Rolle des Schlüssels hier dem Partitionsschlüssel und dem Clustering-Schlüssel von Cassandra, und mehrere Definitionen können in Form einer Liste oder durch Kommas getrennt vorgenommen werden.
Darüber hinaus bietet die ScalarDB-Speicherkomponente vier Funktionen für CRUD-Operationen.
Diese Komponente bietet zusätzlich zur Funktionalität der Speicherkomponente masterlose Transaktionsfunktionen.
Um die Transaktionsfunktion verwenden zu können, müssen Sie zunächst eine TransactionService-Instanz abrufen. Nachdem Sie die Operationen Get, Put, Delete und Scan für die TransactionService-Instanz ausgeführt haben, schreiben Sie die TransactionService-Instanz fest und geben Sie die Operationsdetails in der Datenbank wieder.
Überprüfen Sie den Betrieb der tatsächlichen Anwendung von ScalarDB mit der Beispielanwendung.
Implementieren Sie eine Beispiel-App mit diesen Funktionen.
Bilddiagramm
KEYSPACE:emoney TABLE:account Säule ・ Group_id: Gruppen-ID (Partitionsschlüssel) -Id: Benutzer-ID (Clustering-Schlüssel) ・ Guthaben: Geldbetrag, der dem Benutzer gehört
Führen Sie die oben genannten Vorgänge innerhalb einer Transaktion aus.
Führen Sie die oben genannten Vorgänge innerhalb einer Transaktion aus.
Angenommen, die für den Betrieb erforderliche Anwendung wurde bereits installiert, verwenden Sie gradle, um die Ausführungs-JAR-Datei abzurufen.
export SCHEMATOOL = / home / (Benutzername der eigenen Umgebung) / scalarb / tools / schema
・ Reflektieren Sie die Einstellungsänderung
$ source ~/.bash_profile
・ Erstellen und verschieben Sie ein Verzeichnis
$ mkdir ~/scalardb_sample
$ cd ~/scalardb_sample
$ gradle init --type java-application
$ vi build.gradle
build.gradle
#Ändern Sie die Spezifikation von mainClassName(18. Zeile)
#Vorher ändern
mainClassName = 'App'
#Nach der veränderung
mainClassName = 'sample.emoney.ElectronicMoneyMain'
#Skalare DB-Definition zu Abhängigkeiten hinzugefügt(22. Zeile)
dependencies {
// This dependency is found on compile classpath of this component and consumers.
compile 'com.google.guava:guava:23.0'
compile group: 'com.scalar-labs', name: 'scalardb', version: '1.0.0'
// Use JUnit test framework
testCompile 'junit:junit:4.12'
$ gradle build
OK, wenn BUILD SUCCESS FUL
angezeigt wird
$ vi emoney.sdbql
emoney.sdbql
REPLICATION FACTOR 1;
CREATE NAMESPACE emoney;
CREATE TRANSACTION TABLE emoney.account (
group_id TEXT PARTITIONKEY,
id TEXT CLUSTERINGKEY,
balance INT,
);
$ $SCHEMATOOL/loader emoney.sdbql
Überprüfen Sie das Schema mit cqlsh
$ cqlsh
Stellen Sie sicher, dass sich im Schlüsselbereich Emoney befindet
cqlsh> DESCRIBE KEYSPACES ;
Ausführungsergebnis
emoney system_auth coordinator system_traces
system_schema system system_distributed
Stellen Sie sicher, dass in der Tabelle ein Konto vorhanden ist
cqlsh> use emoney;
cqlsh:emoney> DESCRIBE TABLES ;
Ausführungsergebnis
account
Beenden Sie cqlsh
cqlsh:emoney> exit
Erstellen Sie zwei, eine Klassendatei, die den Konstruktor und die Funktion beschreibt, und eine Ausführungsklassendatei, die Argumente empfängt und die Funktion aufruft.
Erstellen Sie ein Verzeichnis und eine Java-Datei
$ mkdir -p src/main/java/sample/emoney
$ cd src/main/java/sample/emoney
$ vi ElectronicMoney.java
ElectronicMoney.java
package sample.emoney;
//Import hinzufügen
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.scalar.database.config.DatabaseConfig;
import com.scalar.database.service.StorageModule;
import com.scalar.database.service.StorageService;
import com.scalar.database.service.TransactionModule;
import com.scalar.database.service.TransactionService;
import java.io.File;
import java.io.IOException;
import com.scalar.database.api.DistributedTransaction;
import com.scalar.database.api.Get;
import com.scalar.database.api.Put;
import com.scalar.database.api.Delete;
import com.scalar.database.api.Result;
import com.scalar.database.io.IntValue;
import com.scalar.database.io.Key;
import com.scalar.database.io.TextValue;
import com.scalar.database.exception.storage.ExecutionException;
import com.scalar.database.exception.transaction.CommitException;
import com.scalar.database.exception.transaction.CrudException;
import com.scalar.database.exception.transaction.UnknownTransactionStatusException;
import java.util.Optional;
import com.scalar.database.api.Scan;
import com.scalar.database.api.Scanner;
public class ElectronicMoney {
//Klassenvariablen definieren
private final String NAMESPACE = "emoney";
private final String TABLE_NAME = "account";
private final String ID = "id";
private final String GROUP_ID = "group_id";
private final String BALANCE = "balance";
private final StorageService storageService;
private final TransactionService transactionService;
//Konstruktor implementieren
public ElectronicMoney() throws IOException {
File prop_file = new File("/etc/scalar/database.properties");
DatabaseConfig config = new DatabaseConfig(prop_file);
Injector injector = Guice.createInjector(new StorageModule(config));
storageService = injector.getInstance(StorageService.class);
storageService.with(NAMESPACE, TABLE_NAME);
injector = Guice.createInjector(new TransactionModule(config));
transactionService = injector.getInstance(TransactionService.class);
transactionService.with(NAMESPACE, TABLE_NAME);
}
public void charge(String groupId, String id, int amount) throws CrudException, CommitException, UnknownTransact ionStatusException {
//Transaktionsstart
DistributedTransaction tx = transactionService.start();
Key partitionKey = new Key(new TextValue(GROUP_ID, groupId));
Key clusteringKey = new Key(new TextValue(ID, id));
Get get = new Get(partitionKey, clusteringKey);
Optional<Result> result = tx.get(get);
int balance = amount;
if (result.isPresent()) {
int current = ((IntValue) result.get().getValue(BALANCE).get()).get();
balance += current;
}
//Guthaben aktualisieren
Put put = new Put(partitionKey, clusteringKey).withValue(new IntValue(BALANCE, balance));
tx.put(put);
//Transaktions-Commit
tx.commit();
}
public void pay(String groupId, String fromId, String toId, int amount) throws CrudException, CommitException, UnknownTransactionStatusException {
//Transaktionsstart
DistributedTransaction tx = transactionService.start();
//Erhalten Sie Kontoinformationen von Absender und Empfänger
Key partitionKey = new Key(new TextValue(GROUP_ID, groupId));
Key fromKey = new Key(new TextValue(ID, fromId));
Key toKey = new Key(new TextValue(ID, toId));
Get fromGet = new Get(partitionKey, fromKey);
Get toGet = new Get(partitionKey, toKey);
Optional<Result> fromResult = tx.get(fromGet);
Optional<Result> toResult = tx.get(toGet);
if (!fromResult.isPresent()) {
throw new RuntimeException(fromId + " doesn't exist.");
}
if (!toResult.isPresent()) {
throw new RuntimeException(toId + " doesn't exist.");
}
int newFromBalance = ((IntValue) (fromResult.get().getValue(BALANCE).get())).get() - amount;
int newToBalance = ((IntValue) (toResult.get().getValue(BALANCE).get())).get() + amount;
if (newFromBalance < 0) {
throw new RuntimeException(fromId + " doesn't have enough balances.");
}
//Guthaben aktualisieren
Put fromPut = new Put(partitionKey, fromKey).withValue(new IntValue(BALANCE, newFromBalance));
Put toPut = new Put(partitionKey, toKey).withValue(new IntValue(BALANCE, newToBalance));
tx.put(fromPut); tx.put(toPut);
//Transaktions-Commit
tx.commit();
}
public void balances(String groupId) throws ExecutionException {
Key partitionKey = new Key(new TextValue(GROUP_ID, groupId));
Scan scan = new Scan(partitionKey);
Scanner scanner = storageService.scan(scan);
scanner.forEach(r -> {
r.getValue(ID).ifPresent(v -> System.out.print(((TextValue) v).getString().get()));
System.out.print(" : ");
r.getValue(BALANCE).ifPresent(v -> System.out.println(((IntValue) v).get()));
});
}
public void deleteUser(String groupId, String id) throws CrudException, CommitException, UnknownTransactionStatu sException {
//Transaktionsstart
DistributedTransaction tx = transactionService.start();
Key partitionKey = new Key(new TextValue(GROUP_ID, groupId));
Key clusteringKey = new Key(new TextValue(ID, id));
Get get = new Get(partitionKey, clusteringKey);
Optional<Result> result = tx.get(get);
if (!result.isPresent()) {
tx.abort();
return;
}
//Guthaben aktualisieren
Delete delete = new Delete(partitionKey, clusteringKey);
tx.delete(delete);
//Transaktions-Commit
tx.commit();
}
public void close() {
storageService.close();
transactionService.close();
}
}
$ vi ElectronicMoneyMain.java
ElectronicMoneyMain.java
package sample.emoney;
public class ElectronicMoneyMain {
public static void main(String[] args) throws Exception {
String action = null;
int amount = 0;
String group = null;
String to = null;
String from = null;
for (int i = 0; i < args.length; ++i) {
if ("-action".equals(args[i])) {
action = args[++i];
} else if ("-group".equals(args[i])) {
group = args[++i];
} else if ("-amount".equals(args[i])) {
amount = Integer.parseInt(args[++i]);
} else if ("-to".equals(args[i])) {
to = args[++i];
} else if ("-from".equals(args[i])) {
from = args[++i];
} else if ("-help".equals(args[i])) {
printUsageAndExit();
}
}
ElectronicMoney eMoney = new ElectronicMoney();
if (action.equalsIgnoreCase("charge")) {
eMoney.charge(group, to, amount);
} else if (action.equalsIgnoreCase("pay")) {
if (from == null) {
printUsageAndExit();
}
eMoney.pay(group, from, to, amount);
} else if (action.equalsIgnoreCase("balances")) {
eMoney.balances(group);
} else if (action.equalsIgnoreCase("delete")) {
eMoney.deleteUser(group, to);
}
eMoney.close();
}
private static void printUsageAndExit() {
System.err.println(
"ElectronicMoneyMain -action charge/pay/balances/delete -group id -to id [-amount number (needed for charge/pay)] [-from id (needed for pay)]"
);
System.exit(1);
}
}
1000 Gebühr an Benutzer1
$ gradle run --args="-action charge -amount 1000 -group groupA -to user1"
0 Gebühr an Benutzer2
$ gradle run --args="-action charge -amount 0 -group groupA -to user2"
Überprüfen Sie das Gleichgewicht zwischen Benutzer1 und Benutzer2
$ gradle run --args="-action balances -group groupA"
300 Zahlungen von Benutzer1 an Benutzer2
$ gradle run --args="-action pay -amount 300 -group groupA -to user2 -from user1"
Überprüfen Sie das Gleichgewicht zwischen Benutzer1 und Benutzer2
$ gradle run --args="-action balances -group groupA"
Benutzer1 löschen
$ gradle run --args="-action delete -group groupA -to user1"
Überprüfen Sie den Kontostand von Benutzer2 und stellen Sie sicher, dass Benutzer1 gelöscht wurde
$ gradle run --args="-action balances -group groupA"
Ändern Sie "ElectronicMoney.java", um sicherzustellen, dass die Transaktionsfunktion funktioniert.
$ vi ElectronicMoney.java
ElectronicMoney.java(Bezahlfunktion,In der Nähe der Linie 101)
public void pay(String groupId, String fromId, String toId, int amount) throws CrudException, CommitException, UnknownTransactionStatusException {
//Transaktionsstart
DistributedTransaction tx = transactionService.start();
//Erhalten Sie Kontoinformationen von Absender und Empfänger
Key partitionKey = new Key(new TextValue(GROUP_ID, groupId));
Key fromKey = new Key(new TextValue(ID, fromId));
Key toKey = new Key(new TextValue(ID, toId));
Get fromGet = new Get(partitionKey, fromKey);
Get toGet = new Get(partitionKey, toKey);
Optional<Result> fromResult = tx.get(fromGet);
Optional<Result> toResult = tx.get(toGet);
if (!fromResult.isPresent()) {
throw new RuntimeException(fromId + " doesn't exist.");
}
if (!toResult.isPresent()) {
throw new RuntimeException(toId + " doesn't exist.");
}
int newFromBalance = ((IntValue) (fromResult.get().getValue(BALANCE).get())).get() - amount;
int newToBalance = ((IntValue) (toResult.get().getValue(BALANCE).get())).get() + amount;
if (newFromBalance < 0) {
throw new RuntimeException(fromId + " doesn't have enough balances.");
}
//Guthaben aktualisieren
Put fromPut = new Put(partitionKey, fromKey).withValue(new IntValue(BALANCE, newFromBalance));
// ----------------Zusätzliche Zeilen von hier-----------------------
//Fügen Sie eine Anweisung hinzu, die beim Experimentieren immer einen Fehler auslöst
if (newFromBalance >= 0){
throw new RuntimeException("test error.");
}
// ----------------Zusätzliche Zeilen bis hierher-----------------------
//Der Kontostand des Empfängers wird nicht aktualisiert
Put toPut = new Put(partitionKey, toKey).withValue(new IntValue(BALANCE, newToBalance));
tx.put(fromPut); tx.put(toPut);
//Transaktions-Commit
tx.commit();
}
1000 Gebühr an Benutzer1
$ gradle run --args="-action charge -amount 1000 -group groupA -to user1"
0 Gebühr an Benutzer2
$ gradle run --args="-action charge -amount 0 -group groupA -to user2"
Überprüfen Sie den Saldo vor der Ausführung
gradle run --args="-action balances -group groupA"
Versuchen Sie, den Überweisungsprozess auszuführen
gradle run --args="-action pay -amount 300 -group groupA -to user2 -from user1"
gradle run --args="-action balances -group groupA"
Das ist alles zum Ausführen der Beispiel-App. Danke fürs Lesen.
Recommended Posts