redis事务

本文详细介绍了Redis事务的概念,包括其执行过程、三个阶段及命令使用。同时,还提供了使用Spring Boot手动与自动开启Redis事务的具体实现案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概念

在redis中没有隔离级别的概念,都是串行化执行。

事务执行过程:是把事务过程中执行的命令放入队列中(队列中的命令要么都执行,要么都不执行),输入exec命令开始执行事务

在redis中,单条命令是原子性执行的,但是事务不能保证原子性,且没有回滚。事务中任意命令执行失败,其余命令仍会被执行。

事务的三个阶段:

  1. 开始事务
  2. 执行的命令加入队列
  3. 执行事务或回滚

事务命令:

  • watch key1 key2……:监视一个或多个key,如果事务执行之前,这些key被改动,则事务被打断。(类似乐观锁)
  • multi:事务开始
  • exec:执行事务(执行后无论事务成功还是失败,watch加的监控都会被取消掉)
  • discard:回滚事务
  • unwatch:取消监视

 

二、redis客户端如何使用事务

(1)执行事务

(2)回滚事务

(3)事务中异常

1、事务队列中存在命令错误(类似java编译错误),队列中所有命令都不执行

2、事务队列中存在语法性错误(类似java运行时异常),出错的命令不执行,其他命令正常执行

(4)使用watch

1、模拟watch k2 中数据未变动,正常执行的过程如下:

2、模拟watch k2 中数据发生变动,导致事务执行失败,如图:

事务中途使用其他客户端修改k2的值,如下:

 

三、springboot如何使用事务

有两种方式使用redis事务,手动开启自动开启

redis命令对应的RedisTemplate的方法如下:

        RedisTemplate.multi();
        RedisTemplate.exec();
        RedisTemplate.discard();
        RedisTemplate.watch("");
        RedisTemplate.unwatch()

(1)手动开启

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public void test() {
        //设置事务支持
        stringRedisTemplate.setEnableTransactionSupport(true);
        //开启事务
        stringRedisTemplate.multi();
        try {
            stringRedisTemplate.opsForValue().set("k","v");
            stringRedisTemplate.opsForValue().set("k1","v1");
            //提交事务
            List<Object> exec = stringRedisTemplate.exec();
            for (Object o : exec) {
                System.out.println(o);
            }
        } catch (Exception e) {
            e.printStackTrace();
            //回滚事务
            stringRedisTemplate.discard();
        }
        String k1 = stringRedisTemplate.opsForValue().get("k1");
        System.out.println("k1:"+k1);
    }

执行结果打印:

 

(2)自动开启

1、pom

        <!--redis客户端-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--redis事务依赖JDBC事务管理-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--嵌入式数据库h2。配置了jdbc必须要配置数据库,为了方便配置h2。如果项目有mysql的话就不需要h2数据库了-->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>

 2、启动类注册StringRedisTemplate类,并开启事务支持。

@SpringBootApplication
public class DemoApplication {
    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
            throws UnknownHostException {
        StringRedisTemplate template = new StringRedisTemplate();
        //开启事务支持(默认是没有关闭的)
        template.setEnableTransactionSupport(true);
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

3、controller

@RestController
public class DemoController {
    @Autowired
   private DemoService demoService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @RequestMapping("/test")
    public void getValue() throws Exception {
        String k = stringRedisTemplate.opsForValue().get("k1");
        System.out.println("k1原值:"+k);
        try {
            demoService.test();
        } catch (Exception e) {
            System.out.println("redis事务执行失败");
        }
        String k1 = stringRedisTemplate.opsForValue().get("k1");
        System.out.println("k1事务之后的值:"+k1);
    }
}

4、service

@Service
public class DemoServiceImpl implements DemoService {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void test() throws Exception {
        stringRedisTemplate.opsForValue().set("k","v");
        stringRedisTemplate.opsForValue().increment("k1");
        throw new Exception();
    }
}

测试:模拟抛出异常情况

事务执行失败,数据没有被修改

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值