前言:
该篇内容为我对redis的学习记录,欢迎指正批评。文中只是放了部分调试内容,完整的可以根据流程图跟踪。
一.redis incr命令调用流程
DECR和INCR和类似只是一个是增加一个是减少。其余两个命令也大同小异;
二.源码分析
4个命令相应源码,t_string.c中:
voidincrCommand(client *c) {
incrDecrCommand(c,1); //incr每次增加1 命令原型:incr test1
}
voiddecrCommand(client *c) {
incrDecrCommand(c,-1); //incr每次减少1 命令原型:decr test1
}
voidincrbyCommand(client *c) {
longlong incr;
if (getLongLongFromObjectOrReply(c, c->argv[2], &incr, NULL) != C_OK) return; //获得第二个,增加数量
incrDecrCommand(c,incr); //incrby每次增加输入的数 命令原型增加100:incrby test1 100
}
voiddecrbyCommand(client *c) {
longlong incr;
if (getLongLongFromObjectOrReply(c, c->argv[2], &incr, NULL) != C_OK) return; //获得第二个,减少数量
incrDecrCommand(c,-incr); //decrby每次加少输入的数 命令原型减少100:decrby test1 100
}
incrDecrCommand函数源码 ,t_string.c中:
voidincrDecrCommand(client *c, longlong incr) {
longlong value, oldvalue;
robj *o, *new;
o = lookupKeyWrite(c->db,c->argv[1]); //查找有没有对应的键值
if (o != NULL && checkType(c,o,OBJ_STRING)) return; //判断类型
if (getLongLongFromObjectOrReply(c,o,&value,NULL) != C_OK) return; //获得键值中的数据
oldvalue = value;
if ((incr < 0 && oldvalue < 0 && incr < (LLONG_MIN-oldvalue)) ||
(incr > 0 && oldvalue > 0 && incr > (LLONG_MAX-oldvalue))) { //判断不能不能越界,超出long long范围
addReplyError(c,"increment or decrement would overflow");
return;
}
value += incr; //与操作数相加
/*
判断是否大于对象共享整数,value是否在long只最小到最大之间。共享对象整数为大于10000
*/
if (o && o->refcount == 1 && o->encoding == OBJ_ENCODING_INT &&
(value < 0 || value >= OBJ_SHARED_INTEGERS) &&
value >= LONG_MIN && value <= LONG_MAX)
{
new = o;
o->ptr = (void*)((long)value);
} else {
new = createStringObjectFromLongLong(value); //根据数值创建一个long long的robj结构指针
if (o) {
dbOverwrite(c->db,c->argv[1],new); //重写字典
} else {
dbAdd(c->db,c->argv[1],new); //添加字典
}
}
signalModifiedKey(c->db,c->argv[1]); //通知修改了key
notifyKeyspaceEvent(NOTIFY_STRING,"incrby",c->argv[1],c->db->id); //发送事件通知
server.dirty++;
addReply(c,shared.colon);
addReply(c,new);
addReply(c,shared.crlf);
}
三.调试信息(看图片可能看不懂,先看流程图,根据图片再看)
下一个call断点,然后进入incrCommand
打印命令信息,以及调用栈
获得long long对象调试
增加数据部分调试
有键值是覆盖写入