redis事务基本概念
一组按顺序执行的命令集合,具有一次性(一次执行多个命令且只执行一次)、顺序性(命令按顺序执行)、排他性(各个命令之间互不影响),不存在事务原子性(单个命令是具有原子性的),因为一个事务中即使存在具有运行时错误的命令,正确的命令依旧会执行。所有命令只有当执行EXEC时才会执行。
redis事务命令
命令 | 作用 |
---|---|
MULTI | 标记一个事务的开始 |
DISCARD | 取消事务,放弃执行事务块内的所有命令 |
EXEC | 执行事务内的所有命令 |
WATCH key [key …] | 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断,不会被执行 |
UNWATCH | 取消 WATCH 命令对所有 key 的监视 |
redis事务执行
- 开启事务
- 写入命令
- 执行事务
(1)正确执行事务
(2)放弃事务
(3)监视命令
正常执行
监视发挥作用
不存在隔离性的概念
如果执行失败,我们只能通过unwatch命令解锁,再重新watch即可
redis事务异常
(1)运行时异常
命令本身就具有问题,导致事务无法执行
(2)编译型异常
事务队列中存在编译型错误,只有错误的命令不会执行,正确的命令依旧会执行,即事务没有原子性
jedis测试事务
(1)导入依赖
<!-- 导入jedis的依赖 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.2.0</version>
</dependency>
(2)测试
//jedis操作事务
public class Test {
public static void main(String[] args) {
Jedis jedis = new Jedis("127.1.1.0",6379);
//开启事务
Transaction multi = jedis.multi();
try {
//放入命令
multi.flushAll();
multi.set("k1","redis");
multi.set("k2","java");
//执行事务
multi.exec();
} catch (Exception e) {
//有异常,放弃事务
multi.discard();
e.printStackTrace();
} finally {
System.out.println(jedis.get("k1"));
jedis.close();//关闭连接
}
}
}
SpringBoot redisTemplate测试事务
(1)导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
(2)自定义redisTemplate
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
//我们为了自己开发方便,一般直接使用<String,Object>
RedisTemplate<String,Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
//配置具体的序列化方式
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
//String的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//key采用String的序列化
template.setKeySerializer(stringRedisSerializer);
//hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
//value序列化采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
//hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
(3)测试
@SpringBootTest
class Redis02SpringbootApplicationTests {
@Autowired
@Qualifier("redisTemplate")
private RedisTemplate redisTemplate;
@Test
void contextLoads() {
SessionCallback sessionCallback = new SessionCallback() {
@Override
public Object execute(RedisOperations redisOperations) throws DataAccessException {
redisOperations.multi();
redisTemplate.opsForValue().set("k4","java");
redisTemplate.opsForValue().set("k3","redis");
return redisOperations.exec();
}
};
redisTemplate.execute(sessionCallback);
}
}