42源码10跋山涉水深入字典遍历天下无鱼_第1页
42源码10跋山涉水深入字典遍历天下无鱼_第2页
42源码10跋山涉水深入字典遍历天下无鱼_第3页
42源码10跋山涉水深入字典遍历天下无鱼_第4页
42源码10跋山涉水深入字典遍历天下无鱼_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

我们知道Redis⼲字典也会很⼤。当我们使⽤keys命令搜寻指定模式的key时,模式匹配条件的key被找到了,还需要判断key指向的对象是否已经过期。如果过期了就需要从主⼲字典中将该key删除。voidkeysCommand(client*c){dictIterator*di;//迭代器dictEntry*de;迭代器当前的entrysdspatternc->argv[1]->ptr;keys的匹配模intplen=intallkeys;是否要获取所有key,⽤于keys*这样unsignedlongnumkeys=0;void*replylen=//whydi=dictGetSafeIterator(c->db->dict);allkeys=(pattern[0]=='*'&&pattern[1]==while((de=dictNext(di))!=NULL){sdskey=dictGetKey(de);robjif(allkeys||stringmatchlen(pattern,plen,key,sdslen(key),0)){keyobj=if(expireIfNeeded(c->db,keyobj)0)遍历需要对这两个hashtable依次进⾏,先遍历完旧的hashtable,再继续遍历新的hashtable。如果在遍历的过程中进⾏了rehashStep,将已经遍历过的旧的hashtable的元素迁移到了新的hashtable中,那么遍历会不会出现元素的重复?这也是遍历需要考虑的疑难之处,下⾯我们来看看Redis是如何解决这个问题Redis2种迭代器,⼀种是安全迭代器,另⼀}}}}}字典在扩容的时候要进⾏渐进式迁移,会存在新旧两个hashtable。hashtable,再继续遍历新的hashtable。如果在遍历的过程中进⾏了rehashStep,将已经遍历过的旧的hashtable的元素迁移到了新的hashtable中,那么遍历会不会出现元素的重复?这也是遍历需要考虑的疑难之处,下⾯我们来看看Redis是如何解决这个问题Redis为字典的遍历提供了2种迭代器,⼀种是安全迭代器,另⼀i->safei->safe=return}typedefstructdict*dlongindex当前遍历的槽位置,初始化为-1inttable;//ht[0]orht[1]intsafe这个属性⾮常关键,它表示迭代器是否安全dictEntry*entry;//迭代器当前指向的对象dictEntry*nextEntry;//迭代器下⼀个指向的对象longlongfingerprint迭代器指纹,放置迭代过}获取⾮安全迭代器,只读迭代器,允许rehashStepdictIterator*dictGetIterator(dict*d){dictIterator*iter=iter->d=d;iter->table=0;iter->index=-iter->safe=0;iter->entry=NULL;iter->nextEntry=NULL;returniter;}获取安全迭代器,允许触发过期处理,禁⽌rehashStepdictIterator*dictGetSafeIterator(dict*d){dictIterator*i=i->safei->safe=return}typedefstructdictIterator{dict*d;//⽬标字典对象longindex;当前遍历的槽位置,初始化为-inttable;//ht[0]orintsafe;这个属性⾮常关键,它表示迭代器是否安全dictEntry*entry;//迭代器当前指向的对象dictEntry*nextEntry;//迭代器下⼀个指向的对象longlongfingerprint;//迭代器指纹,放置迭代过}获取⾮安全迭代器,只读迭代器,允许rehashStepdictIterator*dictGetIterator(dict*d){dictIterator*iter=iter->d=d;iter->table=0;iter->index=-iter->safe=0;iter->entry=NULL;iter->nextEntry=NULL;returniter;}获取安全迭代器,允许触发过期处理,禁⽌rehashStepdictIterator*dictGetSafeIterator(dict*d){dictIterator*i=dictGetIterator(d);重复,就会禁⽌rehashStep。dictNext对字典进⾏持续遍历,不得调⽤任何可能触发过期判断的函数。不过好处是不影响rehash,代价就是遍历的记,rehashStep就不会执⾏,遍历时元素就不会出现重复。typedeftypedefstruct{dictType*type;void*privdata;dicththt[2];longrehashidx;量unsignedlong}//如果存在安全的迭代器,就禁⽌rehashstaticvoid_dictRehashStep(dict*dif(d->iterators==0)}⾯挂接的链表中的元素可能会被摘⾛,元素的next指针就会发⽣变重复,就会禁⽌rehashStep。改,你只能调⽤dictNext对字典进⾏持续遍历,不得调⽤任何可能触发过期判断的函数。不过好处是不影响rehash,代价就是遍历的记,rehashStep就不会执⾏,遍历时元素就不会出现重复。typedeftypedefstructdict{dictType*type;void*privdata;dicththt[2];longrehashidx;量unsignedlong}//如果存在安全的迭代器,就禁⽌rehashstaticvoid_dictRehashStep(dict*d)if(d->iterators==0)}⾯挂接的链表中的元素可能会被摘⾛,元素的next指针就会发⽣变ifif(dictIsRehashing(iter->d)iter->table==0)dictEntry*dictNext(dictIterator{while(1)if(iter->entry==NULL)遍历⼀个新槽位下⾯的链表,数组的index==0)表

dictht*ht=&iter->d-if(iter->index==-1&&iter-也就是ht[0]if(iter->safe)}else记录迭代器指纹,就好⽐字典的md5}

iter->index++index=0if(iter->index>=(long)ht->size)ifif(dictIsRehashing(iter->d)iter->table==0)dictEntry*dictNext(dictIterator{while(1)if(iter->entry==NULL)遍历⼀个新槽位下⾯的链表,数组的index==0)表

dictht*ht=&iter->d-if(iter->index==-1&&iter-也就是ht[0]if(iter->safe)}else记录迭代器指纹,就好⽐字典的md5iter->fingerprint}

iter->index++;index=0if(iter->index>=(long)ht->size)iteriter->nextEntry=iter->entry-returniter-第⼆个

iter->index=0;ht=&iter->d-}else}}iter->entry=ht->table[iter-}elseiter->entry=iter-}if(iter->entry)键试想如果后⾯发⽣了rehash,当前遍历的链表旧的链表将⼀分为⼆,打散后重新挂接到新数如果rehash的链表是index前⾯的链表,那么iteriter->nextEntry=iter->entry-returniter-第⼆个

如果处于rehashiter->index=0;ht=&iter->d-}else}}iter->entry=ht->table[iter-}elseiter->entry=iter-}if(iter->entry)键试想如果后⾯发⽣了rehash,当前遍历的链表

如果rehash的链表是index前⾯的链表,那么}}return}}return}====(long)d-{if(!(iter->index==-1&&iter->table=={if(iter-iter->d->iterators去掉禁⽌

}}longlongdictFingerprint(dict{longlongintegers[6],hash=0;intj;voiddictReleaseIterator(dictIterator{if(!(iter->index==-1&&iter->table=={if(iter-iter->d->iterators去掉禁⽌

assert(iter->fingerprint}}如果只是某个元素的valuelonglongdictFingerprint(dict*d){longlongintegers[6],hash=0;intj;====(long)d-for(j=0;j<6;{+=hash(~hash)+(hash<<hashhash^(hash>>hash(hash+(hash<<3))+(hashhashhash^(hash>>hash(hash+(hash<<2))+(hashhashhash^(hash>>hashhash+(hash<<}return}值得注意的是在字典扩容时进⾏rehash,将旧数组中的链表迁移到hashhashmod2^n=hashmod2^(n+1)=korkeys指令使⽤了安全迭代器,因为结果不允许重复。那还有其===(long)d-forfor(j=0;j<6;j++){hash+=integers[j];hash=(~hash)+(hash<<21);hash=hash^(hash>>24);hash=(hash+(hash<<3))+(hashhash=hash^(hash>>hash=(hash+(hash<<

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论