Redis(四):del/unlink 命令源码解析 您所在的位置:网站首页 unlink和remove的区别 Redis(四):del/unlink 命令源码解析

Redis(四):del/unlink 命令源码解析

2024-06-02 04:14| 来源: 网络整理| 查看: 265

上一篇文章从根本上理解了set/get的处理过程,相当于理解了 增、改、查的过程,现在就差一个删了。本篇我们来看一下删除过程。

  对于客户端来说,删除操作无需区分何种数据类型,只管进行 del 操作即可。

零、删除命令 del 的定义

  主要有两个: del/unlink, 差别是 unlink 速度会更快, 因为其使用了异步删除优化模式, 其定义如下:

// 标识只有一个 w, 说明就是一个普通的写操作,没啥好说的 {"del",delCommand,-2,"w",0,NULL,1,-1,1,0,0} // 标识为 wF, 说明它是一个快速写的操作,其实就是有一个异步优化的过程,稍后详解 {"unlink",unlinkCommand,-2,"wF",0,NULL,1,-1,1,0,0} 一、delCommand

  delCommand 的作用就是直接删除某个 key 的数据,释放内存即可。

// db.c, del 命令处理 void delCommand(client *c) { // 同步删除 delGenericCommand(c,0); } /* This command implements DEL and LAZYDEL. */ void delGenericCommand(client *c, int lazy) { int numdel = 0, j; for (j = 1; j < c->argc; j++) { // 自动过期数据清理 expireIfNeeded(c->db,c->argv[j]); // 此处分同步删除和异步删除, 主要差别在于对于复杂数据类型的删除方面,如hash,list,set... // 针对 string 的删除是完全一样的 int deleted = lazy ? dbAsyncDelete(c->db,c->argv[j]) : dbSyncDelete(c->db,c->argv[j]); // 写命令的传播问题 if (deleted) { signalModifiedKey(c->db,c->argv[j]); notifyKeyspaceEvent(NOTIFY_GENERIC, "del",c->argv[j],c->db->id); server.dirty++; numdel++; } } // 响应删除数据量, 粒度到 key 级别 addReplyLongLong(c,numdel); }

框架代码一看即明,只是相比于我们普通的删除是多了不少事情。否则也不存在设计了。

二、unlinkCommand

  如下,其实和del是一毛一样的,仅是变化了一个 lazy 标识而已。

// db.c, unlink 删除处理 void unlinkCommand(client *c) { // 与 del 一致,只是 lazy 标识不一样 delGenericCommand(c,1); } 三、删除数据过程详解

  删除数据分同步和异步两种实现方式,道理都差不多,只是一个是后台删一个是前台删。我们分别来看看。

1. 同步删除 dbSyncDelete

  同步删除很简单,只要把对应的key删除,val删除就行了,如果有内层引用,则进行递归删除即可。

// db.c, 同步删除数据 /* Delete a key, value, and associated expiration entry if any, from the DB */ int dbSyncDelete(redisDb *db, robj *key) { /* Deleting an entry from the expires dict will not free the sds of * the key, because it is shared with the main dictionary. */ // 首先从 expires 队列删除,然后再从 db->dict 中删除 if (dictSize(db->expires) > 0) dictDelete(db->expires,key->ptr); if (dictDelete(db->dict,key->ptr) == DICT_OK) { if (server.cluster_enabled) slotToKeyDel(key); return 1; } else { return 0; } } // dict.c, 如上, 仅仅是 dictDelete() 就可以了,所以真正的删除动作是在 dict 中实现的。 int dictDelete(dict *ht, const void *key) { // nofree: 0, 即要求释放内存 return dictGenericDelete(ht,key,0); } // dict.c, nofree: 0:要释放相应的val内存, 1:不释放相应val内存只删除key /* Search and remove an element */ static int dictGenericDelete(dict *d, const void *key, int nofree) { unsigned int h, idx; dictEntry *he, *prevHe; int table; if (d->ht[0].size == 0) return DICT_ERR; /* d->ht[0].table is NULL */ if (dictIsRehashing(d)) _dictRehashStep(d); h = dictHashKey(d, key); // ht[0] 和 ht[1] 如有可能都进行扫描 for (table = 0; table ht[table].sizemask; he = d->ht[table].table[idx]; prevHe = NULL; while(he) { if (dictCompareKeys(d, key, he->key)) { /* Unlink the element from the list */ if (prevH


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有