Redis的高级功能-----事务

概述

事务:事务允许用户将多个命令打包成一个操作来执行,确保这些命令要么全部成功,要么全部失败,从而保证数据的一致性和原子性

事务

事务的优点
原子性:Redis事务可以保证多个命令的原子性执行,即要么全部执行,要么全部不执行。
性能:Redis事务可以将多个命令打包成一个批量操作,从而减少网络通信的开销,提高性能。
一致性:Redis事务可以保证多个命令的一致性,即在执行事务期间,其他客户端不会对这些命令进行修改。
实现方式
MULTI:开始一个事务。
EXEC:执行事务中的所有命令。
DISCARD:取消事务。
WATCH:监视一个或多个键,如果在事务执行期间这些键被修改,事务将被取消。
示例:

/**
     * 事务操作
     * @param isOpenError 是否开启异常
     */
    public void transactionalMethod(boolean isOpenError) {
        redisTemplate.execute(new SessionCallback<List<Object>>() {
            @Override
            public List<Object> execute(RedisOperations operations) {
                operations.multi(); // 开启事务
                ValueOperations<String, String> valueOps = operations.opsForValue();
                valueOps.set("key1", "value1");
                if(isOpenError){
                    int i = 1 / 0;
                }
                valueOps.set("key2", "value2");
                List exec = operations.exec();//提交事务
                return exec;
            }
        });
    }

注意事项

Redis事务不支持回滚操作。
如果在执行事务期间,键被其他客户端修改,那么事务将被取消。
Redis事务不支持嵌套事务。
Redis事务中的命令不能使用事务外的数据。
Redis事务中的命令不支持乐观锁。

解答

Redis 的单线程模型

Redis 的单线程是指其网络事件处理和命令执行是在一个线程中完成的。这意味着,Redis 在处理某一个客户端请求时,其他请求会被挂起,按顺序处理。这确保了单个命令的原子性。

Redis 事务的行为

Redis 的事务由以下几个阶段组成:

  1. 开始事务 (MULTI):将后续命令放入事务队列,但不会立即执行。
  2. 命令入队:每个命令会按顺序被加入事务队列。
  3. 执行事务 (EXEC):Redis 按照事务队列中的顺序一次性执行所有命令。

重要的一点是,Redis 的事务不支持回滚,也没有锁机制。事务内的命令不会在入队时立即检查键的状态,而是在事务执行 (EXEC) 时才实际执行。

为什么其他客户端可以影响事务?

在事务命令入队和实际执行 (EXEC) 之间,事务并未锁住这些键。其他客户端可以同时发送命令并修改键的值。

例如:

  1. 客户端 A 发送:
    MULTI
    GET key1
    SET key1 value1
    
  2. 此时事务队列中仅记录了 GET key1SET key1 value1
  3. 在客户端 A 发送 EXEC 之前,客户端 B 修改了 key1 的值。
  4. EXEC 执行时,事务仍会执行 GET key1SET key1 value1,此时读取和写入的值可能与预期不同。

乐观锁的作用

为了解决这一问题,Redis 提供了乐观锁机制(基于 WATCH)。WATCH 监视一个或多个键,如果在事务执行前这些键被修改,事务会自动取消。流程如下:

  1. 客户端 A 发送:
    WATCH key1
    MULTI
    GET key1
    SET key1 value1
    
  2. 如果 key1EXEC 前被其他客户端修改,事务会中止,EXEC 返回空值。
posted @ 2024-11-22 10:02  daligh  阅读(44)  评论(0)    收藏  举报