Springboot中Redis事务的使用及Lua脚本

环境:springboot2.3.8.RELEASE + Redis5


先对Redis事务做介绍

Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:

  • 批量操作在发送 EXEC 命令前被放入队列缓存。
  • 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
  • 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。

命令介绍:

  1. MULTI
    标记一个事务块的开始。
  2. EXEC
    执行所有事务块内的命令。
  3. DISCARD
    取消事务,放弃执行事务块内的所有命令。

演示:

  1. 正常执行

  1. 取消事务

  1. 事务失败处理1(编译错误)

当编译(语法错误)时,事务会被取消执行。

  1. 事务失败处理2(运行时错误)

运行时错误,只会失败当前失败的命令,对于其他的命令是没有影响的。

总结:redis命令是原子性的,事务是非原子性的。

  1. 利用watch命令进行事务的回滚
    watch命令用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

在watch k1 键后修改k1的值,然后开始事务(也就是说在开始事务前这个key k1已经被修改了)在事务中对k1进行修改,最后执行exec事务提交,返回nil,说明事务回滚。


了解完Redis中的事务,接下来看看在Springboot中如何使用事务。

引入依赖:

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-pool2</artifactId>
</dependency>

配置:

spring:
  redis:
    host: localhost
    port: 6379
    password: 
    database: 2 
    lettuce:
      pool:
        maxActive: 8
        maxIdle: 100
        minIdle: 10
        maxWait: -1  

注意:在springboot中我们直接使用StringRedisTemplate操作redis即可,不用在去配置那些序列化等一些信息。

在StringRedisTemplate中有这么一个方法来执行多个操作。

stringRedisTemplate.exec(SessionCallback callback)
public List<Object> execTransaction() {
		return stringRedisTemplate.execute(new SessionCallback<List<Object>>() {
			@SuppressWarnings({ "rawtypes", "unchecked" })
			@Override
			public List<Object> execute(RedisOperations operations) throws DataAccessException {
				operations.multi() ;
				operations.opsForValue().set("k1", "v1") ;
				operations.opsForValue().set("k2", "v2") ;
				return operations.exec();
			}
		}) ;
	}

执行成功了。

执行LUA脚本

public Long execScript() {
		String script = "local val = redis.call('INCR', KEYS[1]);\n"
				+ "redis.call('SET', KEYS[2], '0');\n"
				+ "redis.call('EXPIRE', KEYS[2], 3600);\n"
				+ "return val" ;
		RedisScript<Long> redisScript = new DefaultRedisScript<>(script) ;
		List<String> keys = new ArrayList<>() ;
		keys.add("sm") ;
		keys.add("pk") ;
		Long id = stringRedisTemplate.execute(redisScript, keys, "0") ;
		return id
	}

通过Lua脚本来保证多个命令执行的原子性

在lua脚本中通过redis.call来执行redis命令。KEYS[...],ARGV[...]

完毕!!!

好心人给个关注+转发好不好谢谢啊

Springboot整合openfeign使用详解

Spring Cloud Sentinel 流控限流

zookeeper实现分布式缓存

Alibaba Nacos作为你的服务注册中心

Alibaba Nacos作为你的配置中心

Alibaba Sentinel 动态规则(动态文件数据源)

zookeeper实现分布式ID

Alibaba Sentinel动态规则(Nacos数据源)

Alibaba Sentinel授权规则

alibaba sentinel 流控使用

SpringCloud Sentinel 整合 zuul

Springboot整合工作流引擎Activiti(三)

SpringCloud zuul 动态网关配置

举报
评论 0