问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

面试官:redis执行setkeyval方法时都发生了什么?

发布网友 发布时间:2024-09-08 01:34

我来回答

1个回答

热心网友 时间:2024-09-28 02:49

小编相信大家都或多或少用过Redis,如果你没用过,那你是不是就得emo一会了,这么好用的东西都没接触过,小编只想说,你们公司还缺不缺人。

今晚这篇文章我们一起来了解一下,redis的set方法究竟是如何运行的,小编将带大家一起以redis的setkeyvalue方法为例单步调试一下redis(不会的偶尔也直接跳过)。

按惯例,先说调试工具

clion

redis6.0.1源码

编译环境-cygwin

cmake

接下来就要开始卷了

注:setkeyvalue具体执行的方法定义在t_string.c文件中。

首先我在客户端执行了setflkeyflvalue方法。通过我们后端打的断点通过setCommand方法走到了具体的功能方法voidsetGenericCommand如下(我们从具体的业务方法开始说,之前的socket连接传送具体命令都不属于具体的功能方法,就不提了,有想了解了可以私聊小编一起过几招)。注:小编在下面代码中做了注释。

voidsetGenericCommand(client*c,intflags,robj*key,robj*val,robj*expire,intunit,robj*ok_reply,robj*abort_reply){longlongmilliseconds=0;/*initializedtoavoidanyharmnesswarning*///如果通过setex方法设置了超时时间if(expire){//获取超时时间给milliseconds赋值if(getLongLongFromObjectOrReply(c,expire,&milliseconds,NULL)!=C_OK)return;//判断时间是否小于等于0if(milliseconds<=0){addReplyErrorFormat(c,"invalidexpiretimein%s",c->cmd->name);return;}//时间单位转换if(unit==UNIT_SECONDS)milliseconds*=1000;}//校验:nx不能互斥设值,xx需要有值if((flags&OBJ_SET_NX&&lookupKeyWrite(c->db,key)!=NULL)||(flags&OBJ_SET_XX&&lookupKeyWrite(c->db,key)==NULL)){addReply(c,abort_reply?abort_reply:shared.null[c->resp]);return;}//设置keyvalue值genericSetKey(c,c->db,key,val,flags&OBJ_SET_KEEPTTL,1);server.dirty++;//设置超时时间if(expire)setExpire(c,c->db,key,mstime()+milliseconds);//对订阅了事件set的客户端进行通知notifyKeyspaceEvent(NOTIFY_STRING,"set",key,c->db->id);//如果设置了超时时间,对订阅了事件expire的客户端进行通知if(expire)notifyKeyspaceEvent(NOTIFY_GENERIC,"expire",key,c->db->id);addReply(c,ok_reply?ok_reply:shared.ok);}

接下来我们主要看genericSetKey方法

voidgenericSetKey(client*c,redisDb*db,robj*key,robj*val,intkeepttl,intsignal){//当前redis中不存在要插入的keyif(lookupKeyWrite(db,key)==NULL){//添加keyvaldbAdd(db,key,val);}else{//覆盖keyvaldbOverwrite(db,key,val);}//增加对val的引用计数incrRefCount(val);//保留设置前指定key的过期时间,6.0版本之后新增的参数if(!keepttl)removeExpire(db,key);if(signal)signalModifiedKey(c,db,key);}

由于我们的执行的key是不存在的,所以这个时候走dbAdd方法,截图为证接下来我们走到dbAdd方法里看一看

voiddbAdd(redisDb*db,robj*key,robj*val){//ptr是key字符串的内存首地址指针,将其封装成一个sds对象sdscopy=sdsdup(key->ptr);//添加keyvalintretval=dictAdd(db->dict,copy,val);//通过宏验证是否添加成功,如果失败直接_exit(1)serverAssertWithInfo(NULL,key,retval==DICT_OK);//这里返回给客户端通知先不管,和本次文章的字符串类型不相关if(val->type==OBJ_LIST||val->type==OBJ_ZSET||val->type==OBJ_STREAM)signalKeyAsReady(db,key);//如果是集群部署,将命令发送给其他节点(slot)if(server.cluster_enabled)slotToKeyAdd(key->ptr);}

这个dbAdd方法主要就是通过key对应的指针首地址创建一个sds对象。然后将sds对象插入到hash表中。

sds:是redis作者自己写的一个字符串数据结构(简单动态字符串),小编猜测,应该是redis整体是用c语言写的,二c语言中是没有字符串这个数据结构的,如果作者不自己封装一个sds,那就得用c语言中的char[]表示一个字符串。而且char[]用起来也很不方便,要自己记录长度,如果遇到字符串结尾还得自己添加\0,并且对于redis这种内存存储的系统,要尽量做到节省内存,就更不能直接用char数组了。hash表:redis里定义为dict结构体。其实就是一个hashtable结构。

typedefstructdict{dictEntry**table;dictType*type;unsignedlongsize;unsignedlongsizemask;unsignedlongused;void*privdata;}dict;

typedefstructdictEntry{voidkey;voidval;structdictEntry*next;}dictEntry;

接下来就是往hash表中(dict)添加具体的元素```c/*往hash表中添加元素*/intdictAdd(dict*d,void*key,void*val){//这里会为要插入的key申请内存和rehash等操作,都是一些hash表基本的操作就不看了dictEntry*entry=dictAddRaw(d,key,NULL);if(!entry)returnDICT_ERR;//setvaldictSetVal(d,entry,val);returnDICT_OK;}#definedictSetVal(d,entry,_val_)do{\if((d)->type->valDup)\(entry)->v.val=(d)->type->valDup((d)->privdata,_val_);\else\(entry)->v.val=(_val_);\}while(0)

redis中set方法插入一个字符串keyval的主流程大概就是这些,大家学废了吗?当然后面添加方法返回后还有一些集群化的代码,我这里是本地起的单机服务,没有走这些代码,就不介绍了。有兴趣的可以私聊小编一起卷。

问君能有几多愁,恰似满屏代码加需求

对一些新技术感兴趣的可以关注公众号:云下凤澜

原文:https://juejin.cn/post/7097999633686724616
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
...了我亲弟弟的女朋友了 她也喜欢我 我该怎么办 他们已经分手了... ...个朋友的老婆你说我该追她吗 他们现在已经分手了 月经第三天有大量血块排出是什么原因 如何关闭360推荐的广告学习关闭360推荐广告 手机浏览器的不雅广告怎么清除 怎样设置浏览器推送内容 学政治对考公务员有优势吗 公务员必须选政治吗 如何提高苹果手机的下载速度 苹果手表有必要买蜂窝版吗苹果手表有必要买蜂窝版吗 cmake如何做到正确链接动态库so? nmake做了什么? cmake是什么 身体缺乏热量的表现 宫颈癌早期和晚期症状 宫颈癌的中期症状表现 依赖性的英文怎么写? 宫颈癌哪些症状 为什么睡觉脚会抽筋 家具有哪些英文 宫颈癌中期的症状 宫颈癌中期症状 睡觉半夜脚为什么抽筋 香山每天几点开门,几点关门,京西旅游攻略夜晚 凌晨一点到北京首都国际机场还有机场大巴吗?我想去后海看夜景,怎么坐 ... 冒险岛怪物掉落(冒险岛2世界boss掉落物品大全介绍_冒险岛怪物掉落(冒 ... 「冒险岛」怪物收藏介绍_「冒险岛」怪物收藏是什么 影响生涯规划的外在因素不包括什么 西北风是从哪向哪吹的什么方向刮的风是西北风 新系统电子承兑拆分教程 腰痹通胶囊的功效和作用 CUDA教程-如何用CMake编译CUDA代码 腰痹通胶囊效果怎么样 华擎H61M-ITX主板芯片 腰痹通胶囊对腰椎间盘突出症引起的腿脚酸麻有什么样的 华擎PV530-ITX主板芯片 抖音里的红包是真的吗 华擎A75M-ITX重要参数 华擎ITX迷你小板如何支持28核心Intel处理器? 华擎H67M-ITX详细参数 华擎H77M-ITX详细参数 华擎FM2A85X-ITX主板芯片 桑树上的桑黄可以吃吗? 珠海换居住证如何办理 名不副实造句用名不副实造句 cad怎么显示标注工具栏? cad命令对话框在哪调出来? 3匹空调外机尺寸多少? 肉丸子汤肉丸大些还是小些好吃? 微信视频号订单如何退货?