ApsaraDB for Redisは、Redisで定義されたトランザクションメカニズムをサポートしています。 MULTI、EXEC、DISCARD、WATCH、およびUNWATCHコマンドを実行して、トランザクションでアトミック操作を実行できます。
Redisのトランザクションは、リレーショナルデータベースのトランザクションとは異なります。 トランザクションの操作が失敗した場合、またはDISCARDコマンドによってトランザクションがキャンセルされた場合、Redisはトランザクションのロールバックを実行しません。
サンプルコード
例1: 2つのクライアントが異なるキーを処理する
サンプルコード:
package transcation.kvstore.aliyun.com;
import java.util.List;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
public class KVStoreTranscationTest {
static final String host = "xxxxxx.m.cnhza.kvstore.aliyuncs.com";
static final int port = 6379;
static final String password = "password";
// Note that these two keys have different content.
static String client1_key = "KVStore-Transcation-1";
static String client2_key = "KVStore-Transcation-2";
public static void main(String[] args) {
Jedis jedis = new Jedis(host, port);
// The password of the ApsaraDB for Redis instance.
String authString = jedis.auth(password);//password
if (!authString.equals("OK")) {
System.err.println("authentication failed: " + authString);
jedis.close();
return;
}
jedis.set(client1_key, "0");
// Start another thread to simulate the other client.
new KVStoreTranscationTest().new OtherKVStoreClient().start();
Thread.sleep(500);
Transaction tx = jedis.multi();// Start the transaction.
//The following operations are submitted to the server as atomic operations.
tx.incr(client1_key);
tx.incr(client1_key);
Thread.sleep(400);// The suspension of the thread does not affect the subsequent operations in the transaction. Other thread operations cannot be performed.
tx.incr(client1_key);
Thread.sleep(300);// The suspension of the thread does not affect the subsequent operations in the transaction. Other thread operations cannot be performed.
tx.incr(client1_key);
Thread.sleep(200);// The suspension of the thread does not affect the subsequent operations in the transaction. Other thread operations cannot be performed.
tx.incr(client1_key);
List<Object> result = tx.exec();// Execute the transaction.
// Parse and display the results.
for(Object rt : result){
System.out.println("Client 1 > transaction in progress> "+rt.toString());
}
jedis.close();
}
class OtherKVStoreClient extends Thread{
@Override
public void run() {
Jedis jedis = new Jedis(host, port);
// The password of the ApsaraDB for Redis instance.
String authString = jedis.auth(password);// password
if (!authString.equals("OK")) {
System.err.println("AUTH Failed: " + authString);
jedis.close();
return;
}
jedis.set(client2_key, "100");
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Client 2 > "+jedis.incr(client2_key));
}
jedis.close();
}
}
}
正しいエンドポイントとパスワードでApsaraDB for Redisインスタンスにアクセスし、上記のJavaコードを実行すると、次の出力が表示されます。 出力は、クライアント1とクライアント2が2つの異なるスレッドで実行されることを示しています。 クライアント1によって提出されたトランザクション動作は、順次に実行される。 クライアント2は、この期間中に別のキーで操作を実行する要求を送信しますが、操作はブロックされます。 クライアント2は、クライアント1のすべてのトランザクション操作が完了するまで待たなければならない。
期待される出力:
Client 2 > 101
Client 2 > 102
Client 2 > 103
Client 2 > 104
Client 1> transaction in progress> 1
Client 1> transaction in progress> 2
Client 1> transaction in progress> 3
Client 1> transaction in progress> 4
Client 1> transaction in progress> 5
Client 2 > 105
Client 2 > 106
Client 2 > 107
Client 2 > 108
Client 2 > 109
Client 2 > 110
例2: 2つのクライアントが同じキーを処理する
例1のコードは、2つのクライアントが同じキーを処理するようにわずかに変更されています。 コードの他の部分は変更されません。
... ...
// これら2つのキーの内容は同じになりました。
静的文字列client1_key = "KVStore-Transcation-1";
静的文字列client2_key = "KVStore-Transcation-1";
... ...
修正されたJavaコードが実行されると、次の出力が表示されます。 2つのクライアントは異なるスレッドで実行されますが、同じキーを処理します。 しかしながら、クライアント1がこのキーを処理するためにトランザクション機構を使用する間、クライアント2はブロックされ、クライアント1の全てのトランザクション動作が完了するまで待たなければならない。
クライアント2 > 101
クライアント2 > 102
クライアント2 > 103
クライアント2 > 104
クライアント1> 進行中のトランザクション> 105
クライアント1> 進行中のトランザクション> 106
クライアント1> 進行中のトランザクション> 107
クライアント1> 進行中のトランザクション> 108
クライアント1> 進行中のトランザクション> 109
クライアント2 > 110
クライアント2 > 111
クライアント2 > 112
クライアント2 > 113
クライアント2 > 114
クライアント2 > 115