Redis 事务

Redis 事务允许将多个命令打包,然后一次性、按顺序地执行。Redis 事务的实现主要通过以下几个命令:MULTIEXECDISCARDWATCH

Redis 事务特点:

  1. 原子性(Atomicity):事务中的所有命令都会被序列化并连续执行,事务在执行过程中不会被其他客户端发送来的命令请求所中断。

  2. 没有隔离级别的概念:在事务执行期间,事务中的命令不会看到其他客户端对数据库所作的变更。

  3. 不保证持久性和一致性:如果服务器在执行事务过程中崩溃,即使部分命令已经被执行,事务也不会被持久化;如果事务中的某个命令失败,其他命令仍然会被执行。

事务的工作流程:

  1. 开始事务 :使用 MULTI 命令开始一个事务。

  2. 命令入队 :在 MULTI 之后输入的所有命令不会立即执行,而是被放入一个队列,客户端会收到一个回复表示命令已成功入队。

  3. 执行事务 :通过 EXEC 命令执行所有队列中的命令。如果事务中的任何命令执行失败,Redis 仍将继续执行事务队列中的剩余命令。事务执行完毕后,会一次性将事务产生的所有结果返回给客户端。

  4. 取消事务 :使用 DISCARD 命令可以取消事务,这将清空事务队列并退出事务。

  5. 乐观锁WATCH 命令可以在事务开始之前监视一个或多个键,在执行 EXEC 命令时,如果任何被监视的键被修改,那么整个事务都会被取消。

源码解析:

Redis的事务功能主要体现在multi.c 文件中,该文件包含了处理事务命令的相关函数。Redis 使用一个叫做 multiState 的结构体来记录事务状态,包括命令队列和被 WATCH 命令监视的键。

当调用 MULTI 命令时,Redis会为当前客户端初始化一个 multiState 结构体,并将其标记为处于事务状态。在事务状态中,客户端发来的命令会被添加到 multiState 的命令队列中而不会被执行。

当调用 EXEC 命令时,Redis会按顺序执行 multiState 的命令队列中的所有命令,并将结果发送给客户端。如果之前有过 WATCH,并且监视的键发生了变化,则事务会被打断,客户端收到空回复表示事务执行失败。

Java代码演示:

以下是使用 Jedis 客户端库在 Java 中操作 Redis 事务的示例:

java 复制代码
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

public class RedisTransactionExample {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);

        // 乐观锁:监视一个key
        jedis.watch("key");

        // 开始事务
        Transaction t = jedis.multi();
        try {
            // 事务中的操作
            t.set("key", "value");
            t.incr("counter");

            // 提交事务
            t.exec();

        } catch (Exception e) {
            // 事务出错,取消事务
            t.discard();
        } finally {
            jedis.unwatch(); // 移除监视
            jedis.close();
        }
    }
}

在这个例子中,我们首先通过 jedis.watch("key") 对 key 进行监视,然后我们通过 jedis.multi() 开始事务,并向事务中添加了一些命令。通过 t.exec() 提交事务,如果在执行 execkey 的值被其他客户端修改了,则事务会被取消,exec 返回 null。如果事务中途出现异常,我们使用 t.discard() 取消事务。

注意事项:

  • Redis事务不支持回滚,即使事务中的某些命令失败,事务也不会回滚之前已执行的命令。
  • Redis 事务中,即使命令语法错误,也会在 EXEC 时全部执行其他命令,错误的命令会导致事务失败。
  • 使用乐观锁时,如果其他客户端修改了被监视的键,事务将不会执行任何命令。

Redis事务虽然具有原子性,但它并不完全等同于传统关系型数据库中的事务。了解其工作原理和限制对于正确使用Redis事务至关重要。

相关推荐
NUZGNAW14 分钟前
Ubuntu 安装redis和nginx
redis·nginx·ubuntu
卓航16 小时前
Redis slowlog使用和实现
redis
波吉爱睡觉17 小时前
Redis反弹Shell
redis·web安全·网络安全
骑着蜗牛闯宇宙18 小时前
Thinkphp8 Redis队列与消息队列Queue
redis·php
是阿建吖!20 小时前
【Redis】初识Redis(定义、特征、使用场景)
数据库·redis·缓存
neoooo20 小时前
《锁得住,才能活得久》——一篇讲透 Redisson 分布式锁的技术实录
java·spring boot·redis
Villiam_AY1 天前
Redis 缓存机制详解:原理、问题与最佳实践
开发语言·redis·后端
GEM的左耳返1 天前
Java面试全攻略:Spring生态与微服务架构实战
spring boot·redis·spring cloud·微服务·kafka·java面试
程序员勋勋11 天前
Redis的String数据类型底层实现
数据库·redis·缓存
颜颜yan_1 天前
Python面向对象编程详解:从零开始掌握类的声明与使用
开发语言·redis·python