Grape命令语法命令含义:去掉给定key的生命周期,将这个key从“volatile”(有生命周期的key)转换为“persistent”』(没有生存时间且永不过期的密钥)。命令格式:PERSIST键命令实战:redis>SETmykey"Hello"OKredis>EXPIREmykey10(integer)1redis>TTLmykey(integer)10redis>PERSISTmykey(integer)1redis>TTLmykey(integer)-1redis>返回值:成功去除生存时间时,返回1。如果key不存在或者key没有设置生存时间,则返回0。源码分析命令入口:/*PERSISTkey*/voidpersistCommand(client*c){//找到这个key,调用lookupKeyWrite函数if(lookupKeyWrite(c->db,c->argv[1])){//如果这个key存在,调用delete函数,调用dictGenericDelete函数if(removeExpire(c->db,c->argv[1])){addReply(c,shared.cone);服务器脏++;}else{addReply(c,shared.czero);}}else{addReply(c,shared.czero);}}这里是persist命令我们可以看到这个命令的执行分为几个阶段:1.找到你要执行persist命令的key看是否存在,如果不存在则直接返回客户端信息存在。如果存在,则调用delete函数去除过期时间,如果删除成功则返回成功信息给客户端,并将aof标志位加1。确定密钥的可用性/*查找写入操作的密钥,并且作为副作用,如果需要,如果达到其TTL,则过期*密钥。**如果键存在,则返回链接值对象;如果键不存在,则返回NULL*在指定的数据库中。*//*找到这个key*/robj*lookupKeyWrite(redisDb*db,robj*key){//首先找出这个key是否过期,过期删除,这个功能在之前的文章中已经介绍过了,这里不再赘述。expireIfNeeded(数据库,密钥);基于上一步,如果key被删除则返回null,否则返回key的值如果*主字典中有相应的条目,则将其删除。否则,密钥永远不会被释放。*/serverAssertWithInfo(NULL,key,dictFind(db->dict,key->ptr)!=NULL);returndictDelete(db->e??xpires,key->ptr)==DICT_OK;}这个过程是判断key是否存在,分为两部分,首先他会检查key是否过期,如果过期则删除it,然后查询key,否则直接搜索key,这里还有一个问题,为什么不先检查key是否存在,再判断是否过期呢?我的想法:Redis将过期时间和key-value存储为两个字典。expire字典中存在的值,key-value字典中一定存在。那么当expire过期的时候,就涉及到了reids的懒删除机制。为了满足设计这个机制的时候,reids会先判断key的过期时间,然后判断key是否存在。如果对redis的删除机制感兴趣,可以参考Redis数据过期策略。真正移除的过程/*搜索并移除一个元素。这是*dictDelete()和dictUnlink()的辅助函数,请查看这些函数的置顶评论*。*/staticdictEntry*dictGenericDelete(dict*d,constvoid*key,intnofree){uint64_th,idx;dictEntry*he,*prevHe;整数表;//我们知道redis中有两个ht,ht[0]和ht[1],如果这两个ht里面没有已用空间,直接返回nullif(d->ht[0].used==0&&d->ht[1].used==0)返回NULL;如果(dictIsRehashing(d))_dictRehashStep(d);//根据key获取他的hash值h=dictHashKey(d,key);//遍历ht[0]和ht[1],如果找到就删除他的key-value,这里是因为删除了expired的时候,我们可以看到外层的调用函数传入了db->e??xpires和key,那么这一块从expire的字典中删除,删除的过程在for语句中,很简单,遍历,如果找到删除,也释放空间。for(table=0;table<=1;table++){idx=h&d->ht[table].sizemask;he=d->ht[table].table[idx];prevHe=NULL;while(he){if(key==he->key||dictCompareKeys(d,key,he->key)){/*取消元素与列表的链接*/if(prevHe)prevHe->next=he->下一个;elsed->ht[table].table[idx]=he->next;如果(!nofree){dictFreeKey(d,他);dictFreeVal(d,he);自由(他);}d->ht[表].used--;还他;}prevHe=他;他=他->下一个;}如果(!dictIsRehashing(d))中断;}返回空值;在设置过期时间这一步,这里我们只需要设计dict的一些操作,比如遍历dict的ht[0],ht[1],删除dict的某个值。大意是先找到钥匙,再放开。因为这里之前的文章已经介绍过了,所以我直接放传送门:dict是怎么找元素的。
