Redis对事务的支持很简单,当一个客户端连接Redis服务时,发出MULTI命令就行进入事务,在执行MULTI命令之后,所要执行的命令并不会执行,而是进入到一个队列中,当最后执行EXEC命令后,才会执行对redis的操作命令,DISCATD为回滚事务。
        RedisTemplate提供了MULTI、EXEC、DISCATD命令的封装,代码如下:

redisTemplate.setEnableTransactionSupport(true);
redisTemplate.multi();
try{
    redisTemplate.opsForValue().set("a", 1);
    int i = 1 / 0;
    redisTemplate.opsForValue().set("b", 2);
    redisTemplate.exec();
    System.out.println("执行成功");
}catch (Exception e){
    redisTemplate.discard();
    e.printStackTrace();
    System.out.println("执行失败");
}

如果不开始事务redisTemplate.setEnableTransactionSupport(true),则会报异常信息:

Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR DISCARD without MULTI

-------------------------------------------------

事务冲突问的解决方案:

针对事务冲突问题:两个事物同时对一个key操作问题。

可以在执行MULTI之前,先执行WATCH命令,可以监听多个,如果在事务执行之前,监听的KEY被其他命令改动,那么事务将会被打断。如果事务正常执行结束了,执行UNWATCH命令取消对KEY的监听。如果在执行WATCH命令之后,EXEC命令或DISCARD命令先被执行了的话,那么就不需要再执行UNWATCH命令了。

乐观锁:每次拿数据时认为别人不会修改,在更新时判断一下版本号是否一致,一样就执行,不一样就不执行。

悲观锁:每次拿数据时上锁,这样别人想拿这个数据就会block,直到它拿到锁。

 Redis事务的三特性:

 1、 单独的隔离操作

        事务中的所有命令都会序列化,按顺序执行。事务在执行过程中,不会被其它客户端发送来的命令请求给打断。

 2、 没有隔离级别的概念

        队列中的命令没有提交之前都不会被执行,因为事务提交前任务指令都不会被实际执行。

 3、 不保证原子性

        执行EXEC后,事务中如果有一个命令执行失败,其他的命令仍然会被执行,没有回滚

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐