参考学习:http://doc.redisfans.com/topic/transaction.html
Redis提供的事务机制,有别于关系型数据库,因为中途执行失败,它会跳过,上面执行的操作并不会回滚!
它是执行一组命令,下面两种情况错误的处理机制稍有区别:
运行时执行错误,入队成功但是执行失败,会跳过继续执行:
语法错误,命令入队失败,事务会取消执行:
redis在事务执行期间也有可能是被其他操作更改的,执行下面代码:
@Test
public void multiNotSafe() {
Jedis anotherJedis = new Jedis();
jedis.set("mu","hello");
Transaction transaction = jedis.multi();
transaction.append("mu", "1");
anotherJedis.append("mu", "hu");
List<Object> execResult = transaction.exec();
System.out.println(Arrays.toString(execResult.toArray()));
System.out.println(anotherJedis.get("mu"));
anotherJedis.close();
}
执行结果:
redis提供了监听机制改观上面的状况,加入Watch后效果如下:
@Test
public void multiWatch() {
Jedis anotherJedis = new Jedis();
jedis.set("mu", "1");
// 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
jedis.watch("mu");
Transaction transaction = jedis.multi();
transaction.append("mu", "1");
transaction.set("new1", "2");
anotherJedis.append("mu", "hu");
List<Object> execResult = transaction.exec();
if (execResult == null || execResult.isEmpty()) {
System.out.println(jedis.get("mu"));
// 乐观锁
} else {
System.out.println(Arrays.toString(execResult.toArray()));
System.out.println(jedis.get("mu"));
}
anotherJedis.close();
}
执行结果:
Watch监听:如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
可以通过下面的伪代码实现重试机制:
method (key) {
watch(key);
Transaction t = openMulti();
t.set();
t.lpush();
Obj result = t.exec();
if(result == null){
method(key);
}
}