Reids命令解析-RENAME
有一天开发突然照过来问,维萨我这个Redis实例这么慢呢?为什么这么慢,于是连上实例SLOWLOG 一看,这些慢日志都是大部分是RENMAE操作导致的,可是为什么RENAME操作会慢呢?不就是改个名字么? 难道它还做了别的事? 又或者学习Linux 的mv 操作? 先copy 再DEL ?
于是带着这个问题,问问来拜访一下REDIS源码,看看为什么RENAME操作会慢的?在Redis中RENAME相关命令有两个 rename、renamenx。
我们找到入库函数 server.c [struct redisCommand redisCommandTable[] = {}],定位到renameCommand,可以发现这两个命令后端都是调用同一个函数[ renameGenericCommand(c,N)],只是这个N这个值不同而已
所以问题就很简单了, 我们只需要知道 [renameGenericCommand] 这个函数到底做了什么操作即可,定位到这个函数不难发现,对于Rename 命令会做以下操作:
- 先对比 rename 中的两个KEY是不是一样,如果不相同则继续
- 对第一个KEY在db 中查找,如果存在则继续,并记录 value 对象地址
- 获取这个KEY 的过期时间,继续下一步
- 尝试着查找第二个KEY,如果第二个KEY存在则删除第二个KEY
- 把第二个KEY名字和第一个KEY的value 作为K-V 添加到DB中
- 如果第一个KEY有过期时间,则为该KEY设置过期时间
- 最后删除掉第一个KEY
精简过得源代码如下:
void renameGenericCommand(client *c, int nx) {
robj *o;
long long expire;
int samekey = 0;
if (sdscmp(c->argv[1]->ptr,c->argv[2]->ptr) == 0) samekey = 1;
if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.nokeyerr)) == NULL) return;
if (samekey) return;
incrRefCount(o);
expire = getExpire(c->db,c->argv[1]);
if (lookupKeyWrite(c->db,c->argv[2]) != NULL) {
dbDelete(c->db,c->argv[2]);
}
dbAdd(c->db,c->argv[2],o);
if (expire != -1) setExpire(c,c->db,c->argv[2],expire);
dbDelete(c->db,c->argv[1]);
}
所以通过以上我们可以得到如下结论:
实际上RENAME = Query * 2 + ADD + [ DEL ] + [ EXPIRE ]
而对于RENAMENX = Query * 2 + ADD + [ EXPIRE ] ,这里一定没有DEL操作
对于内存数据库REDIS 来说, QUERY 、ADD 、EXPIRE 都是很快的,但是对于某些KEY DEL则不一定块,如果这个KEY的内存占用比较多,那么DEL 是个比较慢的过程。
OK,结论似乎有了, 那么需要进一步的来验证一下这个结论,怎么验证呢?很简单,我们可以GET 出来看看这个KEY 有多大, 或者使用 DEBUG OBJECT XXXKEY 看一下序列化后的内存大小。
OK,结论也有了,也验证了,看起来是 大KEY 惹的货啊, 那么对于我们怎么找到这些大KEY,如果进行删除,请查看我的前两篇文章 :)
Reids命令解析-RENAME的更多相关文章
- linux mknod命令解析
linux mknod命令解析 http://www.cnblogs.com/cobbliu/archive/2011/07/05/2389014.html mknod:make node 生成设备 ...
- C#基础:命令解析
1.普通格式命令的解析 例如: RENA<SP>E:\\A.txt<SP>C:\\B.txt<CRLF> (SP -> 空格,CRLF -> 回车加换行 ...
- Appium Android Bootstrap源码分析之命令解析执行
通过上一篇文章<Appium Android Bootstrap源码分析之控件AndroidElement>我们知道了Appium从pc端发送过来的命令如果是控件相关的话,最终目标控件在b ...
- virsh的详细命令解析(一)
virsh的详细命令解析 virsh 有命令模式和交互模式如果直接在vrish后面添加参数是命令模式,如果直接写virsh,就会进入交互模式 virsh list 列出所有的虚拟机,虚拟机的状态有(8 ...
- 重命名文件或文件夹(mv命令与rename命令)
在Linux下重命名文件或目录,可以使用mv命令或rename命令,这里分享下二者的使用方法. mv命令既可以重命名,又可以移动文件或文件夹. 例子:将目录A重命名为B mv A B 例子:将/a目录 ...
- (转)Linux命令:使用dig,nslookup命令解析域名
Linux命令:使用dig命令解析域名 Linux下解析域名除了使用nslookup之外,开可以使用dig命令来解析域名,dig命令可以得到更多的域名信息. dig的全称是 (domain infor ...
- Linux下重命名文件或文件夹(mv命令与rename命令)
在Linux下重命名文件或目录,可以使用mv命令或rename命令 mv ———————————— mv命令既可以重命名,又可以移动文件或文件夹. 例子:将目录A重命名为B mv A B 例子:将/a ...
- angular-cli.json配置参数解析,常用命令解析
1.angular-cli.json配置参数解析 { "project": { "name": "ng-admin", //项目名称 &qu ...
- [Linux] Linux中重命名文件和文件夹的方法(mv命令和rename命令)
原文链接 在Linux下重命名文件或目录,可以使用mv命令或rename命令,这里分享下二者的使用方法. mv命令既可以重命名,又可以移动文件或文件夹. 例子:将目录A重命名为B mv A B 例子: ...
随机推荐
- LNMP源码编译安装
思路:根据Linux系统以及公司网站系统的信息,选择合适的安装包进行安装 一.查看系统信息 # uname -a # 查看内核/操作系统/CPU信息 # ...
- ④JavaScript格式化时间戳
这部分代码是按照网上的教程写的,忘记在哪里看到了
- 使用WebGL加载Google街景图
我们要实现的功能比较简单:首先通过坐标定位.我的位置.地址搜索等方式,调用google map api获取地址信息.然后根据地址信息中的全景信息获取当前缩放级别的全景信息.最终把这些全景信息通过Web ...
- 预览github项目的html文件新方法
原文地址:→看过来 写在前面 关于如何在线预览github中的html文件,其实这是一个很多人知道的东西,但是查资料的时候呢总是找不到正确的答案,并且一开始我也是踩了坑的. 踩坑经历 搜出来的结果大概 ...
- Hibernate笔记一:HIbernate配置-HelloWorld
hibernate介绍: Hibernate是一个开源的对象关系映射框架,它对JDBC进行了轻量级的对象封装,使Java程序员可以随心所欲的使用对象编程思维来操纵数据库. 它不仅提供了从java类到数 ...
- Opencv在linux下安装
Opencv in Linux These steps have been tested for Ubuntu 10.04 but should work with other distros as ...
- click和blur事件冲突解决方案
场景:例如做一个模仿百度搜索的搜索框,输入文字下面会有匹配项,当点击下拉项中的值时,就将值添加到搜索框中同时隐藏下拉框,点击其他地方就直接隐藏下拉框,这时所需要的事件分别为 下拉框事件onclick, ...
- CSS3用法理解
这里只概括了我对CSS3各属性的用法理解.具体每个属性的值,以及例子,看这里 (竟然每篇文章不能低于200字,不能低于200字不能低于200字不能低于200字不能低于200字....请无视)
- OpenGL判断一个点是否可见
关于OpenGL中判断一个点是否可见,可以分成两种情况讨论:点在2D空间中和3D空间中的时候.并且"在2D空间中"可以看作"在3D空间中"的特殊情况. 温馨提示 ...
- Python中的模块介绍和使用
在Python中有一个概念叫做模块(module),这个和C语言中的头文件以及Java中的包很类似,比如在Python中要调用sqrt函数,必须用import关键字引入math这个模块,下面就来了解一 ...