Redis原理:watch命令

在前面的文章中有提到,在multi 前可以通过watch 来观察哪些key,被观察的这些key,会被redis服务器监控,涉及该key被修改时,则在exec 命令执行过程中会被识别出来,exec 就不会再执行命令。

源码分析

// 监控对应的key
void watchCommand(client *c) {int j;if (c->flags & CLIENT_MULTI) {addReplyError(c,"WATCH inside MULTI is not allowed");return;}/* No point in watching if the client is already dirty. */if (c->flags & CLIENT_DIRTY_CAS) {addReply(c,shared.ok);return;}for (j = 1; j < c->argc; j++)// 按指定的key进行监控watchForKey(c,c->argv[j]);addReply(c,shared.ok);
}
void watchForKey(client *c, robj *key) {list *clients = NULL;listIter li;listNode *ln;watchedKey *wk;/* Check if we are already watching for this key */// 当前已经监控的keylistRewind(c->watched_keys,&li);// 检查是否在监控列表while((ln = listNext(&li))) {wk = listNodeValue(ln);if (wk->db == c->db && equalStringObjects(key,wk->key))return; /* Key already watched */}/* This key is not already watched in this DB. Let's add it */// 获取监控的客户端列表// db->watched_keys是全局缓存的列表clients = dictFetchValue(c->db->watched_keys,key);if (!clients) {// 没有则创建clients = listCreate();dictAdd(c->db->watched_keys,key,clients);incrRefCount(key);}// 记录新的watchKey内容/* Add the new key to the list of keys watched by this client */wk = zmalloc(sizeof(*wk));wk->key = key; // 当前的keywk->client = c; // 当前的客户端wk->db = c->db; // 当前的数据库wk->expired = keyIsExpired(c->db, key); // 是否过期incrRefCount(key);listAddNodeTail(c->watched_keys,wk); // 加入客户端的列表listAddNodeTail(clients,wk); // 加入全局列表
}

watch 命令,做的事情其实也很简单,就是将当前客户端与key 进行关联,并把监控的key加入全局列表中,该全局列表。

当key有变更时,会调用signalModifiedKey进行通知。

void signalModifiedKey(client *c, redisDb *db, robj *key)
{// 监控的key进行刷新touchWatchedKey(db, key);trackingInvalidateKey(c, key, 1);
}
// 如果在multi之前有watch某些key,则该key的所以异动都会要执行该方法
// 并进行重置client的
void touchWatchedKey(redisDb *db, robj *key) {list *clients;listIter li;listNode *ln;if (dictSize(db->watched_keys) == 0) return;clients = dictFetchValue(db->watched_keys, key);if (!clients) return;/* Mark all the clients watching this key as CLIENT_DIRTY_CAS *//* Check if we are already watching for this key */listRewind(clients,&li);while((ln = listNext(&li))) {watchedKey *wk = listNodeValue(ln);client *c = wk->client;if (wk->expired) {/* The key was already expired when WATCH was called. */if (db == wk->db &&equalStringObjects(key, wk->key) &&dictFind(db->dict, key->ptr) == NULL){/* Already expired key is deleted, so logically no change. Clear* the flag. Deleted keys are not flagged as expired. */wk->expired = 0;goto skip_client;}break;}// 客户端增加标识,告知该客户端有被污染c->flags |= CLIENT_DIRTY_CAS;/* As the client is marked as dirty, there is no point in getting here* again in case that key (or others) are modified again (or keep the* memory overhead till EXEC). */// 移除所有的keyunwatchAllKeys(c);skip_client:continue;}
}

该方法会进行相应key的处理,并为持有该key的客户端,将其标识增加CLIENT_DIRTY_CAS,该标识会在exec命令中判断,如果有,说明watch的key已经被修改,不执行相关的命令。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/41648.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DeepSeek助力文案,智能音箱如何改变你的生活?

你好&#xff0c;我是三桥君 你有没有为写智能音箱的宣传文案而抓耳挠腮过&#xff1f;三桥君在这方面可是有些感想&#xff0c;今天就来给你唠唠怎么用DeepSeek写出超赞的智能音箱宣传文案。 首先&#xff0c;你得给DeepSeek喂足“料”。这就好比做饭&#xff0c;你得准备好各…

二叉树的前,中,后序遍历

我们来了解一下二叉树的遍历&#xff0c;话不多说 二叉树的遍历的概念&#xff1a; 二叉树有四种遍历方式&#xff0c;分别为前序遍历&#xff0c;中序遍历&#xff0c;后序遍历和层序遍历&#xff0c;但我们今天谈谈前三种&#xff0c;并实现它 前序遍历&#xff1a; 按照根…

Linux网站搭建(新手必看)

1.宝塔Linux面板的功能 宝塔面板是一款服务器管理软件&#xff0c;可以帮助用户建立网站&#xff0c;一键配置服务器环境&#xff0c;使得用户通过web界面就可以轻松的管理安装所用的服务器软件。 2. 宝塔Linux面板的安装 宝塔官网地址&#xff1a;宝塔面板 - 简单好用的Linu…

secp256k1的模数P是如何选择的?

在区块链和现代密码学中&#xff0c;secp256k1 椭圆曲线以其高安全性和高效运算性能而著称。你可能注意到&#xff0c;secp256k1 的曲线方程为 而其中的模数 p 被定义为 那么&#xff0c;为何会选择这样一个看似复杂的数呢&#xff1f;本文将从多个角度为你详细解析这一选择背后…

本地文生图使用插件(Stable Diffusion)

1. 插件下载&#xff08;github&#xff09; 1.1 直接Avaliable中点击安装&#xff08;方案一&#xff09; 1.2 Install from URL中输入URL&#xff08;方案二&#xff09; 1.3 直接下载复制到extensions目录&#xff08;方案三&#xff09; 2. 模型下载&#xff08;Huggingf…

鸿蒙-全屏播放页面(使用相对布局)---持续更新中

最终实现效果图&#xff1a; 实现步骤 创建FullScreenPlay.ets全品播放页面 并将其修改为启动页面。 全屏播放&#xff0c;屏幕必然横过来&#xff0c;所以要将窗口横过来。 编辑 src/main/ets/entryability/EntryAbility.ets 若写在/EntryAbility.ets中&#xff0c;则所有…

C++ 多线程简要讲解

std::thread是 C11 标准库中用于多线程编程的核心类&#xff0c;提供线程的创建、管理和同步功能。下面我们一一讲解。 一.构造函数 官网的构造函数如下&#xff1a; 1.默认构造函数和线程创建 thread() noexcept; 作用&#xff1a;创建一个 std::thread 对象&#xff0c;但…

每天认识一个设计模式-建造者模式:复杂对象的“装配式革命“

一、前言 在软件开发的广袤领域中&#xff0c;随着项目规模日益庞大、业务逻辑愈发复杂&#xff0c;对象的创建过程也变得千头万绪。 早期简单的对象创建方式&#xff0c;在面对复杂对象时&#xff0c;逐渐显露出代码臃肿、耦合度高、可维护性差等弊端&#xff0c;设计模式的…

动态IP与静态IP该如何选?

一、当IP地址成为"网络身份" 2023年亚马逊封号潮中&#xff0c;某杭州卖家因登录IP频繁切换&#xff08;早8点在纽约&#xff0c;午间瞬移到东京&#xff09;&#xff0c;触发平台风控导致账号冻结。这类"时空错乱症"揭示了跨境电商的生存法则&#xff1a…

蓝桥与力扣刷题(蓝桥 蓝桥骑士)

题目&#xff1a;小明是蓝桥王国的骑士&#xff0c;他喜欢不断突破自我。 这天蓝桥国王给他安排了 N 个对手&#xff0c;他们的战力值分别为 a1,a2,...,an&#xff0c;且按顺序阻挡在小明的前方。对于这些对手小明可以选择挑战&#xff0c;也可以选择避战。 身为高傲的骑士&a…

Linux--文件

ok&#xff0c;我们今天了解一下Linux中的文件 理解“文件” 狭义理解 ⽂件在磁盘⾥磁盘是永久性存储介质&#xff0c;因此⽂件在磁盘上的存储是永久性的磁盘是外设&#xff08;即是输出设备也是输⼊设备&#xff09;磁盘上的⽂件本质是对⽂件的所有操作&#xff0c;都是对外…

Linux-数据结构-哈夫曼树-哈希表-内核链表

一.哈夫曼树 哈夫曼树&#xff08;Huffman Tree&#xff09;是一种特殊的二叉树&#xff0c;其定义和原理如下&#xff1a; 【1】定义 哈夫曼树是一种带权路径长度最短的二叉树。给定一组权值&#xff0c;将这些权值作为叶子节点的权值构造一棵二叉树&#xff0c;若该树的带…

前端抽象化,打破框架枷锁:统一路由的设计

个人博客原文地址 此文章并不适合初级前端来看&#xff0c;它是抽象的架构设计&#xff0c;需要一定的TS基础和抽象思维&#xff0c;若带着思考的读完本文章相信会让你感到充实 当然你也可以复制&#xff0c;然后在自己项目中去实现它&#xff0c;然后用起来 只要你是在写前端…

Docker 搭建部署 仓库的搭建以及网络设置

安装docker 一、关闭防火墙和SELinux 1.1systemctl stop firewalld 1.2setenfoce 0 二、配置内核转发以及网桥过滤 2.1vi /etc/sysctl.d/k8s.conf [rootopeneuler system]# vi /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables 1 net.bridge.bridge-nf-call-ip…

OSPF五种报文分析(仅部分比较重要的)

OSPF五种报文分别是&#xff1a; hello报文&#xff0c;DBD数据库描述报文&#xff0c;LSR链路状态请求报文&#xff0c;LSU链路状态更新报文&#xff0c;LSACK链路状态确认包 以下是这五种报文的详细解读&#xff1a; 1. Hello报文 作用&#xff1a; 用于邻居的发现、建立和…

【测试开发】OKR 小程序端黑盒测试报告

【测试报告】OKR 小程序端 项目名称版本号测试负责人测试完成日期联系方式OKR 小程序端4.0马铭胜2025-03-2515362558972 1、项目背景 1.1 OKR 用户端 在如今这个快节奏的时代中&#xff0c;个人和组织的成长往往依赖于清晰、明确且意义深远的目标。然而&#xff0c;如何设定…

【C++】内存模型分析

在 C 语言中&#xff0c;程序运行时的内存通常被划分为以下几个区域&#xff1a; 代码区&#xff08;Text Segment&#xff09;常量区&#xff08;Constant Segment&#xff09;全局/静态区&#xff08;Data Segment&#xff0c;包含静态数据段和 BSS 段&#xff09;堆区&…

关于解决Ubuntu终端及系统字体大小的问题

在Ubuntu中调整终端和系统字体大小可以通过以下方法&#xff08;可能不仅仅只是这几种&#xff09;实现&#xff1a; 1. 调整系统字体大小 打开终端并输入以下命令&#xff0c;安装GNOME Tweaks&#xff0c;等待安装完成&#xff1a; sudo apt install gnome-tweaks 接着进行…

java8循环解压zip文件---实现Excel文件数据追加

java8循环追加Excel数据 实际遇到问题&#xff1a;定期获取zip文件&#xff0c;zip文件内有几个固定模板的Excel文件&#xff0c;有的Excel文件可能还包含多个sheet。 有段时间一次性获取到好几个zip包&#xff0c;需要将这些包都解压&#xff0c;并且按照不同的文件名、sheet进…

内网渗透技术 Docker逃逸技术(提权)研究 CSMSF

目录 如何通过上传的webshell判断当前环境是否是物理环境还是Docker环境 方法一&#xff1a;检查文件系统 方法二&#xff1a;查看进程 方法三&#xff1a;检查网络配置 方法四&#xff1a;检查环境变量 方法五&#xff1a;检查挂载点 总结 2. 如果是Docker环境&#x…