设为首页 收藏本站
查看: 722|回复: 0

[经验分享] redis之字符串命令源码解析(三)

[复制链接]

尚未签到

发表于 2016-12-20 11:19:00 | 显示全部楼层 |阅读模式
形象化设计模式实战             HELLO!架构
 

redis之字符串命令源码解析(一)

redis之字符串命令源码解析(二)
前面已经将set get命令的原理与过程作了详细的解析,下面对一些常用的命令做一些简单讲解,前提是前面的已经明白。

1、append方法解析

 

t_string.c中的appendCommand方法:

void appendCommand(redisClient *c) {
size_t totlen;
robj *o, *append;
// 取出键相应的值对象
o = lookupKeyWrite(c->db,c->argv[1]);
// 如果键值对不存在
if (o == NULL) {
// 键值对不存在,创建一个新的
c->argv[2] = tryObjectEncoding(c->argv[2]);
dbAdd(c->db,c->argv[1],c->argv[2]);
incrRefCount(c->argv[2]);
//获取字符串对象中字符串值的长度
totlen = stringObjectLen(c->argv[2]);
} else {
// 键值对存在。。。
/* Key exists, check type */
// 检查类型
if (checkType(c,o,REDIS_STRING))
return;
/* "append" is an argument, so always an sds */
// 检查追加操作之后,字符串的长度是否符合 Redis 的限制
append = c->argv[2];
totlen = stringObjectLen(o)+sdslen(append->ptr);
//检查给定字符串长度 len 是否超过限制值 512 MB
if (checkStringLength(c,totlen) != REDIS_OK)
return;
//解除key的共享,之后就可以进行修改操作(采用的方法是新建一个robj对象,覆盖掉原有的)
        o = dbUnshareStringValue(c->db,c->argv[1],o);
        //执行追加操作
        o->ptr = sdscatlen(o->ptr,append->ptr,sdslen(append->ptr));
        totlen = sdslen(o->ptr);
}
// 向数据库发送键被修改的信号
signalModifiedKey(c->db,c->argv[1]);
// 发送事件通知
notifyKeyspaceEvent(REDIS_NOTIFY_STRING,"append",c->argv[1],c->db->id);
// 将服务器设为脏
server.dirty++;
// 发送回复(字符的长度)
addReplyLongLong(c,totlen);
}
大致可图解为:

DSC0000.png



2、incrby方法解析

void incrbyCommand(redisClient *c) {
long long incr;
//将第二个参数转化成long long类型,指向incr
if (getLongLongFromObjectOrReply(c, c->argv[2], &incr, NULL) != REDIS_OK) return;
incrDecrCommand(c,incr);
}

void incrDecrCommand(redisClient *c, long long incr) {
long long value, oldvalue;
robj *o, *new;
// 取出值对象
o = lookupKeyWrite(c->db,c->argv[1]);
// 检查对象是否存在,以及类型是否正确
if (o != NULL && checkType(c,o,REDIS_STRING)) return;
// 取出对象的整数值,并保存到 value 参数中
if (getLongLongFromObjectOrReply(c,o,&value,NULL) != REDIS_OK) return;
// 检查加法操作执行之后值释放会溢出
// 如果是的话,就向客户端发送一个出错回复,并放弃设置操作
oldvalue = value;
if ((incr < 0 && oldvalue < 0 && incr < (LLONG_MIN-oldvalue)) ||
(incr > 0 && oldvalue > 0 && incr > (LLONG_MAX-oldvalue))) {
addReplyError(c,"increment or decrement would overflow");
return;
}
// 进行加法计算,并将值保存到新的值对象中
// 然后用新的值对象替换原来的值对象
value += incr;
new = createStringObjectFromLongLong(value);
if (o)
dbOverwrite(c->db,c->argv[1],new);
else
dbAdd(c->db,c->argv[1],new);
// 向数据库发送键被修改的信号
signalModifiedKey(c->db,c->argv[1]);
// 发送事件通知
notifyKeyspaceEvent(REDIS_NOTIFY_STRING,"incrby",c->argv[1],c->db->id);
// 将服务器设为脏
server.dirty++;
// 返回回复
addReply(c,shared.colon);
addReply(c,new);
addReply(c,shared.crlf);
}

大致可图解为:

DSC0001.jpg

 

这里说下“addReply(c,shared.colon);”这行代码,shared.colon是什么?

Redis 在内部使用了一个Flyweight 模式:通过预分配一些常见的值对象,并在多个数据结构之间共享这些对象,程序避免了重复分配的麻烦,也节约了一些CPU时间。redis.c的createSharedObjects创建了shared
shared.colon = createObject(REDIS_STRING,sdsnew(":"));
由可见如果运行incrby test 3,如果test不存在,那么服务器返回的应该是":3\r\n",可以用telnet连接试试。

 

 

总体来看,Redis的结构设计得有许多巧妙之处,为实现字符串各种需求打下了很好的基础,后序还将剖析Redis相比memcache比较特殊的结构。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-316942-1-1.html 上篇帖子: NoSQL数据库性能大比较:MongoDB、Redis、Tokyo Tyrant 下篇帖子: Redis学习笔记(十)——过期时间、访问限制与缓存
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表