Redis(十三)redis事务

这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战

Redis作为一个非关系型数据库,其也是有事务操作的。

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

(1)批量操作在发送 EXEC 命令前被放入队列缓存。

(2)收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。

(3)在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。

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

(1)开始事务。

(2)命令入队。

(3)执行事务。

但是redis的事务和mysql的事务还是有很大区别的,mysql执行过程中出现错误,数据会回滚,而redis事务执行过程中失败则不会回滚。

Redis的事务可以看做是一个批量执行命令的一个脚本。

这里关注的不是事务执行过程中每条命令是否都执行成功,而是,执行当前的事务是否成功。

一:linux命令

// 开始事务
127.0.0.1:6379> multi
OK
// 设置健值
127.0.0.1:6379> set a aaaa
QUEUED
// 设置健值
127.0.0.1:6379> set b bbbb
QUEUED
// 设置健值
127.0.0.1:6379> set c cccc
QUEUED
// 执行事务,其实redis的事务就是一个批处理命令的一个脚本
127.0.0.1:6379> exec
1) OK
2) OK
3) OK
复制代码

二:PHP命令

// 开启事务
    $res = $redis->multi();
 
    $res = $redis->set('a','aaa');
    var_dump($res);
    echo "<hr>";
 
    $res = $redis->set('b','bbb');
    var_dump($res);
    echo "<hr>";
 
    $res = $redis->set('c','bbb');
    var_dump($res);
    echo "<hr>";
 
    // 执行事务
    $res = $redis->exec();
 
    var_dump($res);
复制代码

以上只是对redis事务简单的应用,大概就是这样,主要应用其是一个批处理的命令。

三:基于redis事务的乐观锁实现

解释:乐观锁(Optimistic Lock), 顾名思义,就是很乐观。

每次去拿数据的时候都认为别人不会修改,所以不会上锁。

watch命令会监视给定的key,当exec时候如果监视的key从调用watch后发生过变化,则整个事务会失败。

也可以调用watch多次监视多个key。这样就可以对指定的key加乐观锁了。

注意watch的key是对整个连接有效的,事务也一样。

如果连接断开,监视和事务都会被自动清除。

当然了exec,discard,unwatch命令都会清除连接中的所有监视。

// 监视 count 值
    $redis->watch("count");
    // 开启事务
    $redis->multi();
    // 操作count
    $time = time();
    $redis->set("count", $time);
 
    // 模拟并发下其他进程进行set count操作 请执行下面操作
    // 在shell命令行中执行 set count issimulate;
 
    sleep(40);
    // 提交事务
    $res = $redis->exec();
 
    $result = $redis->get('count');
 
    if ($res) {
        // 成功...
        echo "success:" . $result ;
        echo "<hr>";
        return;
    }
    // 失败...
    echo "fail:" . $result ;
    echo "<hr>";
 
复制代码

这段测试代码可能要解释一下:

首先我们先监控键count,开启事务之后,将count键的值设置成当前时间戳,程序睡眠40秒,再执行事务操作。这是在理想情况下,就是上边这段代码在没有任何外力影响的情况下的执行事务成功,输出

Success:1502547852
复制代码

上面是事务执行成功的结果,我们现在来模拟事务执行失败的情况,很简单,还是上边那段代码,在浏览器中执行之后,程序会睡眠40秒,我们在这个时间里模拟另一个进程修改count键的值,在shell中执行set count issimulate;,watch监控的健的值在事务执行过程中被另一进程改变,则此次事务执行失败。输出

fail:issimulate
复制代码

其实回过头来看,当不同进程修改同一个值得时候,使用事务,就相当于给其加了一个乐观锁。

四:redis事务命令

序号

命令及描述

1

DISCARD 
  取消事务,放弃执行事务块内的所有命令。
复制代码

2

EXEC 
  执行所有事务块内的命令。
复制代码

3

MULTI 
  标记一个事务块的开始。
复制代码

4

UNWATCH 
  取消 WATCH 命令对所有 key 的监视。
复制代码

5

WATCH   key [key ...] 
  监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
复制代码

有好的建议,请在下方输入你的评论。

欢迎访问个人博客
guanchao.site

欢迎访问小程序:

在这里插入图片描述