| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 大数据 -> Redis | 事物源码阅读 —— watch -> 正文阅读 |
|
[大数据]Redis | 事物源码阅读 —— watch |
? ? ? ?上次阅读事务的源码时,主要阅读了?multi、exec 和 discard 相关的命令,文章地址如下:Redis | 事务源码阅读,这次把上次没有看完的部分看接着看一下。 Redis?的 watch?数据结构 ? ? ? ??关于?watch 存在于几个数据结构当中,基本上在?redisServer、redisCient 和 redisDb 当中,它们大致的关系如下: ? ? ? ? 该示意图是一个大致的示意图,不太保证准确。其中,dict 用于保存监视的?key,而 dict 的 value 是一个 list 数据结构,list 中保存了监视指定 key 的客户端。 Redis 的 watch 命令 ? ? ? ?Redis 的 watch 命令用于监控指定的?key,它的代码在 multi.c 文件中,其代码如下。
? ? ? ? 我们知道,watch 命令不能在 multi 命令后面执行。因此在?watchCommand 函数中首先判断是否执行过 multi 命令,如果执行了 multi 命令则返回错误。 ? ? ? ? 然后调用 watchForKey 来把指定的 key 进行添加,watchForKey?的代码如下:
? ? ? ? 看上面的代码,首先会查找指定的 keys 是否加入监视列表,如果没有加入则进行加入。其中在调用 listAddNodeTail 函数时,第二个参数 wk 的类型是?watchedKey 结构体,该结构体的定义如下:
? ? ? ? 可以看到,该结构体中有指定的 key?和所属的数据库(一个 Redis 实例默认有 16 个 DB,我们可以通过 select 命令来切换数据库)。 Redis 的 unwatch 命令 ? ? ? ?Redis 的 unwatch 命令比较简单,就是取消指定的被监控的 key,该代码如下。
? ? ? ?首先需要调用?unwatchAllKeys 函数,取消监控相关的 key,然后将?redisClient 中的 flags?的?REDIS_DIRTY_CAS 位进行复位。unwatchAllKeys 的源码如下:
? ? ? ? 代码中将 list 和 dict 中对应的 key 进行了删除。其实并不是删除 key ,而是删除监视的 key 对应的客户端,如果删除的后没有客户端再监控该 key 了,则把对应的 dict 也进行删除。 如何监控变量是否被改变 ? ? ? ? 在 Redis 中使用 watch 命令对 key 进行监控后,Redis?如何知道哪个被监控的 key 被修改了呢?在 multi.c 文件中有一个 touchWatchedKey 的函数,该函数用来告诉客户端,它监控的 key 被修改了。代码如下:
? ? ? ?在 touchWatchedKey 函数中,先判断当前操作的 key 是否是被监控的 key,如果是监控的 key,就对 redisClient 的 flags 标志的?REDIS_DIRTY_CAS 位进行置位。那么哪些操作会调用 touchWatchedKey 函数呢?我们来接着看代码,在 db.c 文件中有一个?signalModifiedKey 函数,该函数调用了 touchWatchedKey 函数,那么又是谁调用了 signalModifiedKey 函数呢?看下面的截图。 ? ? ? ?从图中可以看到,调用?signalModifiedKey 函数的地方很多,几乎所有对 key 进行操作的函数都会调用 signalModifiedKey 函数,比如?setKey、delCommand、hsetCommand?等。也就所有修改 key 的值的函数,都会去调用 signalModifiedKey 来检查是否修改了被 watch 的 key,只要是修改了被 watch 的 key,就会对 redisClient 的 flags 设置 REDIS_DIRTY_CAS?位。当执行 execCommand 函数时,就会检查是否存 redisClient 的 flags 的?REDIS_DIRTY_CAS?位是否被置位,如果置位则不执行事务。关于 exeCommand 函数的介绍在上篇文章中介绍过,稍后简单的进行回顾。 ? ? ? ? 同样的,除了存在 signalModifiedKey 函数以外,还有一个?signalFlushedDb?函数,该函数与 signalModifiedKey 函数的功能类似。就不再赘述了。 回顾 execCommand 函数 ? ? ? ? 上篇文章介绍了 execCommand 函数,这里我们进行一个简单的回顾,关键是看执行 execCommand 函数时的对于 flags 标志位的判断。代码如下: ? ? ? ? 上面的关键代码 if 中就是对 REDIS_DIRTY_CAS 的判断,除了判断是否对 REDIS_DIRTY_CAS 置位外,还对 REDIS_DIRTY_EXEC 进行了判断,当开启事务后,如果有输入错误的命令,或者命令使用不正确时会将 redisClient 的 flags 标志位的?REDIS_DIRTY_EXEC 置位。那么,当提交了 exec 后就会给出相应的提示。 总结 ? ? ? ? 关于 Redis 事务的源码就基本上看完了。主要包括 multi、exec、discard 三个事务命令的源码,还有 watch、unwatch 两个用于监视 key 的乐观锁命令的源码,包括它们数据结构,还包括一些和事务相关的标志位,分别是?REDIS_MULTI、REDIS_DIRTY_CAS?和 REDIS_DIRTY_EXEC,第一个是用于事务相关的,后两个是用于影响 exec 命令执行的标志。 ? ? ? ? 在看源码的时候,我发现我阅读源码的顺序是有问题的。因为一些关键的数据结构我并没有去看,因此在读源码的时候不知道一些数据结构之间的关系,需要返回去看相关的数据结构。但是我觉得这样看好像也没有什么问题,有些数据结构就算我提前去看,也未必能够明白其用意。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 13:52:53- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |