设为首页 加入收藏

TOP

高频Redis面试题解析:Redis 事务是否具备原子性?
2023-07-26 08:17:54 】 浏览:68
Tags:高频 Redis 解析

一个事务从开始到结束通常会经历以下三个阶段:


1、事务开始


客户端发送 MULTI 命令,服务器执行 MULTI 命令逻辑。


服务器会在客户端状态(redisClient)的 flags 属性打开 REDIS_MULTI 标识,将客户端从非事务状态切换到事务状态。


2、命令入队


接着,用户可以在客户端输入当前事务要执行的多个命令。


当客户端切换到事务状态时,服务器会根据客户端发来的命令来执行不同的操作。


我们先看看事务队列是如何实现的


每个 Redis 客户端都有自己的事务状态,对应的是客户端状态(redisClient)的 mstate 属性。


事务状态(mstate)包含一个事务队列(FIFO 队列),以及一个已入队命令的计数器。


事务队列是一个 multiCmd 类型数组,数组中每个 multiCmd 结构都保存了一个如入队命令的相关信息:指向命令实现函数的指针,命令的参数,以及参数的数量。


最后我们再看看入队列的源码


当然了,还有我们上面提到的,如果命令入队出错时,会打开客户端状态的 REDIS_DIRTY_EXEC 标识。


3、事务执行


客户端发送 EXEC 命令,服务器执行 EXEC 命令逻辑。


1、Redis 事务不支持事务回滚机制


Redis 事务执行过程中,如果一个命令执行出错,那么就返回错误,然后还是会接着继续执行下面的命令。


下面我们演示一下:


高频Redis面试题解析:Redis 事务是否具备原子性?


2、但是其实 Redis 意义上是支持原子性的


正常??况下,它也是要不所有命令执行成功,要不一个命令都不执行。


我们下面演示一下:


全部执行成功的:


高频Redis面试题解析:Redis 事务是否具备原子性?


一个都不执行:


高频Redis面试题解析:Redis 事务是否具备原子性?


这就是上面提到的,在事务开始后,用户可以输入事务要执行的命令;在命令入事务队列前,会对命令进行检查,如果命令不存在或者是命令参数不对,则会返回错误可客户端,并且修改客户端状态。


当后面客户端执行 EXEC 命令时,服务器就会直接拒绝执行此事务了。


所以说,Redis 事务其实是支持原子性的!即使 Redis 不支持事务回滚机制,但是它会检查每一个事务中的命令是否错误。


但是我们要注意一个点就是:Redis 事务不支持检查那些程序员自己逻辑错误。例如对 String 类型的数据库键执行对 HashMap 类型的操作!


我很赞同 Redis 作者的想法


首先,MySQL 和 Redis 的定位不一样,一个是关系型数据库,一个是 NoSQL。


MySQL 的 SQL 查询是可以相当复杂的,而且 MySQL 没有事务队列这种说法,SQL 真正开始执行才会进行分析和检查,MySQL 不可能提前知道下一条 SQL 是否正确。所以支持事务回滚是非常有必要的~


但是,Redis 使用了事务队列来预先将执行命令存储起来,并且会对其进行格式检查的,提前就知道命令是否可执行了。所以如果只要有一个命令是错误的,那么这个事务是不能执行的。


Redis 作者认为基本只会出现在开发环境的编程错误其实在生产环境基本是不可能出现的(例如对 String 类型的数据库键执行 LPUSH 操作),所以他觉得没必要为了这事务回滚机制而改变 Redis 追求简单高效的设计主旨



】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇成功实现Navicat访问Linux中安装.. 下一篇MongoDB副本集存储回收

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目