We have some cases that users wish to run multiple operations in one transaction. This feature will provide a way that users can start a transaction, run some operations and commit or cancel the transaction. This kind of transaction can automatically be canceled if the connection between clients and servers is broken.
The basic MiniTransaction API is
MiniTransaction newTransaction() throws GoblinException;
TransResponse commitTransaction(MiniTransaction trans) throws GoblinException;
Type: Condition
Category | Remark |
---|---|
withVersionCond | check if the version is same as given when executing transaction |
withExistCond | check if key exists when executing transaction |
withUdfCond | check if user defined meta of the key meets the pre-defined conditioning logic when executing transaction |
Type: Transaction
Method | Remark |
---|---|
put | put a kv in this transaction |
get | get a kv in this transaction |
delete | delete a kv in this transaction |
Here is the example that use mini-transaction to do a balance transfer:
String fromAccount = "UserA";
String toAccount = "UserB";
long balance = 100;
// use a transaction to get balance of A and B at the same time
MiniTransaction txn1 = client.newTransaction();
txn1.get(fromAccount);
txn1.get(toAccount);
TransResponse transResponse = client.commitTransaction(txn1);
GetResponse getResponseA = (GetResponse) transResponse.getResults().get(0);
GetResponse getResponseB = (GetResponse) transResponse.getResults().get(1);
// transfer balance from A to B in one transaction, which only succeed when two balance account don't change
MiniTransaction txn2 = client.newTransaction();
long newBalanceForA = Long.parseLong(new String(getResponseA.getValue().get().getContent())) - balance;
long newBalanceForB = Long.parseLong(new String(getResponseB.getValue().get().getContent())) + balance;
txn2.withVersionCond(fromAccount, getResponseA.getVersion(), CompareOp.EQUAL);
txn2.withVersionCond(toAccount, getResponseB.getVersion(), CompareOp.EQUAL);
txn2.put(fromAccount, newBalanceForA.toString());
txn2.put(toAccount, newBalanceForB.toString());
client.commitTransaction(txn2);
- Client starts a transaction, then do some operations, and finally commits the transaction.
- Server will take action only when commitTransaction is invoked.
- When commitTransaction is invoked, server records all the operations in the transaction, and lock the keys in alphabetically to avoid deadlock.
- Then server will execute the operations in the transaction one by one.
- All the results in one transaction are persisted in one raft entry to guarantee atomicity.
- When precondition is set in newTransaction, the transaction will check if it is matched only when commitTransaction is invoked. This is more like a pessimistic locking.
- When an operation(put/delete) is invoked in a transaction, the related keys will be locked to prevent others to touch on server side.
- This mini-transaction only exists in the memory of the connected server, and will be cleaned up when server is rebooted. User will get exception if commitTransaction is invoked after server is rebooted.
- Before the commitTransaction returns successfully, it cannot guarantee that the transaction operations succeed.
- If the client loses connection with the server for commitTransaction, the transaction will be removed and nothing will happen.