可以一次、顺序的、排他性的执行多个命令。
事务整个流程
1 Redis中使用MULTI命令开启一个事务,客户端可以向服务器端发送多条命令,但是不会立即执行,而是进入一个队列中,只有当执行EXEC时,队列中所有的命令才会去执行。可以通过DISCARD命令清空事务队列。
正常执行
> MULTI
OK
> INCR foo
QUEUED
> INCR bar
QUEUED
> EXEC
1) (integer) 1
2) (integer) 1
Jedis jedis=new Jedis("192.168.209.101",6379);
Transaction transaction=jedis.multi();
transaction.set("a","a");
transaction.set("b","b");
List<Object> execResult = transaction.exec();
System.out.println(JSON.toJSONString(execResult));
放弃事务
如图中,设置一个两个值,最后执行discard,放弃事务。前面的值设置失败
全体连坐
如图中,第二个命令参数错误,在最后执行exec后出现错误,前面设置的值无效。
如果出现命令明显不对,相当于入队失败,将会导致整个事务执行失败
\color{#FF0000}{如果出现命令明显不对,相当于入队失败,将会导致整个事务执行失败}
如果出现命令明显不对,相当于入队失败,将会导致整个事务执行失败
冤头债主
如图中,第二个命令,将一个字符串值执行加1的操作,提交事务后除了该命令执行错误,因为只有在执行的过程中裁才知道key对应的value是什么类型,其他的都会执行成功
开启事务后,命令入队,成功的入队的,都会执行,就算有一个执行异常,也不会影响其他命令的执行
\color{#FF0000}{开启事务后,命令入队,成功的入队的,都会执行,就算有一个执行异常,也不会影响其他命令的执行}
开启事务后,命令入队,成功的入队的,都会执行,就算有一个执行异常,也不会影响其他命令的执行
watch监控
得到的是中途被更改的结果,事务中的修改操作执行失败。
用discard:
/**
* 入队失败
*/
@Test
public void test14(){
Jedis jedis=new Jedis("192.168.209.101",6379);
Transaction transaction=jedis.multi();
transaction.set("a","a");
transaction.set("b","b");
try{
System.out.println(1/0);
}catch (Exception e){
transaction.discard();
return;
}
transaction.exec();
}
用watch、multi、exec、discard模拟交易
/**
* watch
*/
@Test
public void test16(){
//模拟交易
int modify=10;
Jedis jedis=new Jedis("192.168.209.101",6379);
//监控user1的账户余额
jedis.watch("user1:balance");
if(modify>Integer.parseInt(jedis.get("user1:balance"))){
//余额不足
jedis.unwatch();
}else{
//可以交易
Transaction transaction=jedis.multi();
//user1账户减
transaction.decrBy("user1:balance",modify);
//user2账户加
transaction.incrBy("user2:balance",modify);
try{
//执行其他操作
}catch (Exception e){
//执行异常,放弃执行事务,放弃监控
transaction.discard();
return;
}
//提交事务
transaction.exec();
}
}
https://my.oschina.net/u/4526289/blog/8645437