Spring Data Redis 教程

Redis 事务简介

本章节将介绍 Spring Data Redis 对 Redis 事务的支持。

什么是事务?

事务是数据库中一个单独的执行单行(Unit),事务就是由一种数据操纵语言DML语句组成,这一组DML要么全不成功要么全部失败,是一个整体。

事务应该具有4个属性(ACID 特性):

  • 原子性(atomicity):一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。

  • 一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

  • 隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

  • 持久性(durability):持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

什么是 Redis 事务?

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

  • 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

  • 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

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

一个事务从开始到执行会经历以下三个阶段:

(1)开始事务

(2)命令入队

(3)执行事务

以下是一个事务的例子, 它先以 MULTI 命令开始一个事务, 然后将多个命令入队到事务中,最后由 EXEC 命令触发事务, 一并执行事务中的所有命令:

D:\server\redis-x64-5.0.14.1>redis-cli
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set username "tom"
QUEUED
127.0.0.1:6379> set password "aaaaa"
QUEUED
127.0.0.1:6379> get username
QUEUED
127.0.0.1:6379> get password
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) "tom"
4) "aaaaa"
127.0.0.1:6379>

上面事务中,先分别添加 username 和 password 键,然后再获取它们的值。

Spring Data Redis 事务

Redis 通过 multi、exec 和 discard 命令为事务提供支持。这些操作 RedisTemplate 提供了支持。然而,RedisTemplate 并不能保证用相同的连接运行事务中的所有操作(可能事务中的语句被多个连接执行)。

Spring Data Redis 提供了 SessionCallback 接口,用于需要使用同一连接执行多个操作时,例如使用 Redis 事务时。以下示例使用 multi 方法:

// 执行一个事务
List<Object> txResults = redisTemplate.execute(new SessionCallback<List<Object>>() {
  public List<Object> execute(RedisOperations operations) throws DataAccessException {
    operations.multi();
    operations.opsForSet().add("key", "value1");
    // 这将包含事务中所有操作的结果
    return operations.exec();
  }
});
System.out.println("Number of items added to set: " + txResults.get(0));

RedisTemplate 使用其 value、hash key 和 hash value 的序列化器,在返回之前对 exec 的所有结果进行反序列化。exec 还有一个额外的方法,它允许您为事务结果传递一个定制的序列化程序。方法定义如下:

  • List<Object> exec() 执行用 multi() 启动的事务中所有排队的命令。

  • List<Object> exec(RedisSerializer<?> valueSerializer) 执行一个事务,使用提供的 RedisSerializer 来反序列化任何byte[] 或 byte[] 集合结果。

提示:

从1.1版开始,RedisConnection 和 RedisTemplate 的 exec 方法进行了重要更改。以前,这些方法直接从连接器返回事务的结果。这意味着数据类型通常与 RedisConnection 方法返回的数据类型不同。例如,zAdd 返回一个布尔值,指示元素是否已添加到排序集。大多数连接器将此值作为 long 值返回,Spring Data Redis 执行转换。另一个常见的区别是,大多数连接器都会为诸如 set 之类的操作返回状态回复(通常是字符串,OK)。这些回复通常被 Spring Data Redis 丢弃。

在1.1之前,不会对 exec 的结果执行这些转换。此外,结果没有在 RedisTemplate 中反序列化,因此它们通常包括原始字节数组。如果此更改破坏了应用程序,请在 RedisConnectionFactory 上将 convertPipelineAndTxResults 设置为 false 以禁用此行为。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号