在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
前言事务是关系型数据库的特征之一,那么作为 Redis 有事务吗这个答案可能会令很多人感到意外,
接下来让我们依次执行以下命令来体会一下 multi //开启事务 set name lonely_wolf //设置 name,此时 Redis 会将命令放入队列 set age 18 //设值 age,此时 Redis 会将命令放入队列 get name //获取 name,此时 Redis 会将命令放入队列 exec //提交事务,此时会依次执行队列里的命令,并依次返回结果 执行完成之后得到如下效果: Redis 事务实现原理
typedef struct client { uint64_t id;//客户端唯一 id multiState mstate; //MULTI 和 EXEC 状态(即事务状态) //...省略其他属性 } client;
typedef struct multiState { multiCmd *commands;//存储命令的 FIFO 队列 int count;//命令总数 //...省略了其他属性 } multiState;
typedef struct multiCmd { robj **argv;//用来存储参数的数组 int argc;//参数的数量 struct redisCommand *cmd;//命令指针 } multiCmd; 我们以上面事务的示例截图中事务为例,可以得到如下所示的一个简图: Redis 事务 ACID 特性传统的关系型数据库中,一个事务一般都具有 A - 原子性在讨论事务的原子性之前,我们先来看 模拟事务在执行命令前发生异常。依次执行以下命令: multi //开启事务 set name lonely_wolf //设置 name,此时 Redis 会将命令放入队列 get //执行一个不完成的命令,此时会报错 exec //在发生异常后提交事务 最终得到了如下图所示的结果,我们可以看到,当命令入队的时候报错时,事务已经被取消了: 模拟事务在执行命令前发生异常。依次执行以下命令: flushall //为了防止影响,先清空数据库 multi //开启事务 set name lonely_wolf //设置 name,此时 Redis 会将命令放入队列 incr name //这个命令只能用于 value 为整数的字符串对象,此时执行会报错 exec //提交事务,此时在执行第一条命令成功,执行第二条命令失败 get name //获取 name 的值 最终得到了如下图所示的结果,我们可以看到,当执行事务报错的时候,之前已经成功的命令并没有被回滚,也就是说在执行事务的时候某一个命令失败了,并不会影响其他命令的执行,即 Redis 中的事务为什么不会滚 这个问题的答案在 总结起来主要就是
C - 一致性一致性指的就是事务执行前后的数据符合数据库的定义和要求。这一点 I - 隔离性事务中的所有命令都会按顺序执行,在执行 D - 持久性如果 watch 命令上面我们讲述 首先打开一个客户端一,依次执行以下命令: flushall //清空数据库 multi //开启事务 get name //获取 name,此时正常返回 nil set name lonely_wolf //设置 name get name //获取 name,此时正常应该返回 lonely_wolf 得到如下效果图: 这时候我们先不执行事务,打开另一个客户端二,来执行一个命令 客户端二执行成功了,这时候再返回到客户端一执行 可以发现,第一句话返回了 是的,在 watch 命令的作用
下面还是让我们通过一个示例来演示一下。 打开一个客户端一,依次执行如下命令: flushall //清空数据库 watch name //监视 name multi //开启事务 set name lonely_wolf //设置 name set age 18 // 设置 age get name //获取 name get age //获取 age 执行之后得到如下效果图: 这时候再打开一个客户端二,执行 然后再回到客户端一执行 watch 原理分析下面是一个 typedef struct redisDb { dict *watched_keys; //被 watch 命令监视的 key int id; //Database ID //...省略了其他属性 } redisDb; 可以看到, 总结本文主要介绍了 到此这篇关于Redis事务为什么不支持回滚 的文章就介绍到这了,更多相关Redis事务回滚 内容请搜索极客世界以前的文章或继续浏览下面的相关文章希望大家以后多多支持极客世界! |
请发表评论