加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程 > 正文

如履薄冰:Redis懒惰删除的庞大捐躯

发布时间:2018-12-14 13:40:37 所属栏目:编程 来源:老钱
导读:各人都知道 Redis 是单线程的,可是 Redis 4.0 增进了懒惰删除成果,懒惰删除必要行使异步线程对已删除的节点举办内存接纳,这意味着 Redis 底层着实并不是单线程,它内部尚有几个特另外鲜为人知的帮助线程。 这几个帮助线程在 Redis 内部有一个出格的名称

接下来我们继承追踪平凡工具的异步删除 lazyfreeFreeObjectFromBioThread 是怎样举办的,请细心阅读代码注释。

  1. void lazyfreeFreeObjectFromBioThread(robj *o) {  
  2.     decrRefCount(o); // 低落工具的引用计数,假如为零,就开释  
  3.     atomicDecr(lazyfree_objects,1); // lazyfree_objects 为待开释工具的数目,用于统计  
  4. }  
  5. // 镌汰引用计数  
  6. void decrRefCount(robj *o) {  
  7.     if (o->refcount == 1) {  
  8.         // 该开释工具了  
  9.         switch(o->type) {  
  10.         case OBJ_STRING: freeStringObject(o); break;  
  11.         case OBJ_LIST: freeListObject(o); break;  
  12.         case OBJ_SET: freeSetObject(o); break;  
  13.         case OBJ_ZSET: freeZsetObject(o); break;  
  14.         case OBJ_HASH: freeHashObject(o); break;  // 开释 hash 工具,继承追踪  
  15.         case OBJ_MODULE: freeModuleObject(o); break;  
  16.         case OBJ_STREAM: freeStreamObject(o); break;  
  17.         default: serverPanic("Unknown object type"); break;  
  18.         } 
  19.         zfree(o);  
  20.     } else {  
  21.         if (o->refcount <= 0) serverPanic("decrRefCount against refcount <= 0");  
  22.         if (o->refcount != OBJ_SHARED_REFCOUNT) o->refcount--; // 引用计数减 1  
  23.     }  
  24. }  
  25. // 开释 hash 工具  
  26. void freeHashObject(robj *o) {  
  27.     switch (o->encoding) {  
  28.     case OBJ_ENCODING_HT:  
  29.         // 开释字典,我们继承追踪  
  30.         dictRelease((dict*) o->ptr);  
  31.         break;  
  32.     case OBJ_ENCODING_ZIPLIST:  
  33.         // 假如是压缩列表可以直接开释  
  34.         // 由于压缩列表是一整块字节数组  
  35.         zfree(o->ptr);  
  36.         break;  
  37.     default:  
  38.         serverPanic("Unknown hash encoding type");  
  39.         break;  
  40.     }  
  41. }  
  42. // 开释字典,假如字典正在迁徙中,ht[0] 和 ht[1] 别离存储旧字典和新字典  
  43. void dictRelease(dict *d)  
  44. {  
  45.     _dictClear(d,&d->ht[0],NULL); // 继承追踪  
  46.     _dictClear(d,&d->ht[1],NULL);  
  47.     zfree(d);  
  48. }  
  49. // 这里要开释 hashtable 了  
  50. // 必要遍历第一维数组,然后继承遍历第二维链表,双重轮回  
  51. int _dictClear(dict *d, dictht *ht, void(callback)(void *)) {  
  52.     unsigned long i;  
  53.     /* Free all the elements */  
  54.     for (i = 0; i < ht->size && ht->used > 0; i++) {  
  55.         dictEntry *he, *nextHe;  
  56.         if (callback && (i & 65535) == 0) callback(d->privdata);  
  57.         if ((he = ht->table[i]) == NULL) continue;  
  58.         while(he) {  
  59.             nextHe = he->next;  
  60.             dictFreeKey(d, he); // 先开释 key  
  61.             dictFreeVal(d, he); // 再开释 value  
  62.             zfree(he); // 最后开释 entry  
  63.             ht->used--;  
  64.             he = nextHe;  
  65.         }  
  66.     }  
  67.     /* Free the table and the allocated cache structure */  
  68.     zfree(ht->table); // 可以接纳第一维数组了  
  69.     /* Re-initialize the table */  
  70.     _dictReset(ht);  
  71.     return DICT_OK; /* never fails */  

这些代码散落在多个差异的文件,我将它们凑到了一块便于读者阅读。从代码中我们可以看到开释一个工具要深度挪用一系列函数,每种工具都有它奇异的内存接纳逻辑。

04.5.9.4 行列安详

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读