云数据库Redis版支持Redis中定义的事务(transaction)机制。
场景介绍
您可以使用MULTI,EXEC,DISCARD,WATCH,UNWATCH指令用来执行原子性的事务操作。
说明 Redis中定义的
事务,并不是关系数据库中严格意义上的事务。当Redis事务中的某个操作执行失败,或者用
DISCARD取消事务时候,Redis不会执行事务回滚。
代码示例1:两个client操作不同的key
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"; //**注意这两个key的内容是不同的 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); // ApsaraDB for Redis的实例密码 String authString = jedis.auth(password);//password if (!authString.equals("OK")) { System.err.println("认证失败: " + authString); jedis.close(); return; } jedis.set(client1_key, "0"); // 启动另一个thread,模拟另外的client new KVStoreTranscationTest().new OtherKVStoreClient().start(); Thread.sleep(500); Transaction tx = jedis.multi();//开始事务 // 以下操作会集中提交服务器端处理,作为“原子操作” tx.incr(client1_key); tx.incr(client1_key); Thread.sleep(400);//此处Thread的暂停对事务中前后连续的操作并无影响,其他Thread的操作也无法执行 tx.incr(client1_key); Thread.sleep(300);//此处Thread的暂停对事务中前后连续的操作并无影响,其他Thread的操作也无法执行 tx.incr(client1_key); Thread.sleep(200);//此处Thread的暂停对事务中前后连续的操作并无影响,其他Thread的操作也无法执行 tx.incr(client1_key); List<Object> result = tx.exec();//提交执行 // 解析并打印出结果 for(Object rt : result){ System.out.println("Client 1 > 事务中> "+rt.toString()); } jedis.close(); } class OtherKVStoreClient extends Thread{ @Override public void run() { Jedis jedis = new Jedis(host, port); // ApsaraDB for Redis的实例密码 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(); } } }
运行结果1
在输入了正确的云数据库Redis版实例访问地址和密码之后,运行以上Java程序,输出结果如下。从中可以看到client1和 client2在两个不同的Thread中,client1所提交的事务操作都是集中顺序执行的,在此期间尽管client2是对另外一个key进行操作,它的命令操作也都被阻塞等待,直至client1事务中的全部操作执行完毕。
Client 2 > 101 Client 2 > 102 Client 2 > 103 Client 2 > 104 Client 1 > 事务中> 1 Client 1 > 事务中> 2 Client 1 > 事务中> 3 Client 1 > 事务中> 4 Client 1 > 事务中> 5 Client 2 > 105 Client 2 > 106 Client 2 > 107 Client 2 > 108 Client 2 > 109 Client 2 > 110
代码示例2:两个client操作相同的key
对以上的代码稍作改动,使得两个client操作同一个key,其余部分保持不变。
... ... //**注意这两个key的内容现在是相同的 static String client1_key = "KVStore-Transcation-1"; static String client2_key = "KVStore-Transcation-1"; ... ...
运行结果2
再次运行修改后的此Java程序,输出结果如下。可以看到不同线程中的两个client在操作同一个key,但是当client1利用事务机制来操作这个key时,client2被阻塞不得不等待client1事务中的操作完全执行完毕。
Client 2 > 101 Client 2 > 102 Client 2 > 103 Client 2 > 104 Client 1 > 事务中> 105 Client 1 > 事务中> 106 Client 1 > 事务中> 107 Client 1 > 事务中> 108 Client 1 > 事务中> 109 Client 2 > 110 Client 2 > 111 Client 2 > 112 Client 2 > 113 Client 2 > 114 Client 2 > 115