相关命令
multi:开启事务
exec:提交事务
discard:回滚事务
watch:监视key,如果key被改变,则打断事务执行
unwatch:取消监视
事务特征(ACID)
普通关系型数据库:
要求整个事务都要符合其原子性(Atomicity), 一致性(Consistency), 隔离性(Isolation), 持久性(Durability)。
redis事务特征:
每一条命令都具有独立的原子性,所以redis的事务特征仅仅是保证批量的提交或者放弃提交。
执行过程
- watch设置监视key,如果key被其他客户端改变,打断事务执行,exec返回为空数组。这个命令其实也要谨慎使用。
- multi命令用于开启一个事务,接收到的后续命令均不会被立即执行,而是放到一个队列中,等待执行。
- exec命令被调用时,事务队列中的命令将被逐个执行,但执行发生错误的时候,其他命令依旧会继续执行。此命令的返回值是一个数组,会返回每条命令的执行情况。
- discard命令百调用时,事务回滚,其实就是清空队列,放弃提交的操作。
- unwatch取消监视
@Autowired
private RedisTemplate<String, String> redisTemplate;
@RequestMapping(value = "/api/v1/test", method = RequestMethod.GET)
public ResultBody query4largeCar() {
String key1 = "key1";
String key2 = "key2";
// 测试事务提交 start
try {
// 设置开启事务支持
redisTemplate.setEnableTransactionSupport(true);
// 监视key事务中的key,如果key被其他客户端改变,打断事务执行,exec返回为空数组
redisTemplate.watch(Arrays.asList(key1,key2));
// 启动事务
redisTemplate.multi();
ValueOperations<String, String> operations = redisTemplate.opsForValue();
// 插入缓存
operations.set(key1,"333", 1, TimeUnit.HOURS);
operations.set(key2,"333", 1, TimeUnit.HOURS);
// 提交事务
List<Object> objects = redisTemplate.exec();
System.out.println(objects);
// 事务执行完成,取消监视
redisTemplate.unwatch();
// 检查事务提交情况
System.out.println("==========事务提交,88888代表成功========="+operations.get(key1));
System.out.println("==========事务提交,88888代表成功========="+operations.get(key2));
}catch (Exception e){
e.printStackTrace();
}
// 测试事务回滚 start
try {
// 设置开启事务支持
redisTemplate.setEnableTransactionSupport(true);
// 监视key事务中的key,如果发生改变,那么表明事务失败,打断事务执行
redisTemplate.watch(Arrays.asList(key1,key2));
// 启动事务
redisTemplate.multi();
ValueOperations<String, String> operations = redisTemplate.opsForValue();
// 插入缓存
operations.set(key1,"xxxxx", 1, TimeUnit.HOURS);
operations.set(key2,"xxxxx", 1, TimeUnit.HOURS);
// 回滚事务
redisTemplate.discard();
// 事务执行完成,取消监视
redisTemplate.unwatch();
// 检查事务提交情况
System.out.println("==========事务回滚,xxxxx代表失败========="+operations.get(key1));
System.out.println("==========事务回滚,xxxxx代表失败========="+operations.get(key2));
}catch (Exception e){
e.printStackTrace();
}
return new ResultBody(ApiResultEnum.SUCCESS);
}
我的示例
/**
* Redis事务操作
* @param value
* @return
*/
@RequestMapping("/redis/transaction/userCount")
@ResponseBody
public String redisTransaction(int value){
String key="user_count";
try{
// 开启事务支持
redisTemplate.setEnableTransactionSupport(true);
// 监视数据key
redisTemplate.watch(key);
// 开启事务
redisTemplate.multi();
// 预处理执行语句
redisTemplate.opsForSet().add(key,value);
// 执行事务处理
redisTemplate.exec();
// 事务成功取消监视
redisTemplate.unwatch();
}catch(Exception e){
// 事务回滚
redisTemplate.discard();
// 解除监视
redisTemplate.unwatch();
e.printStackTrace();
return "failed";
}
return "success";
}