乐趣区

关于c:Redis命令DEL与UNLINK的区别如何正确删除大Key

背景

  • 在这篇文章中做过应用 del 命令删除大 key 的试验,后果是 del 命令随着 key 的增大,主线程阻塞的工夫就越长。
  • 这与之前看 redis5.0.8 版本的代码中对于多线程删除操作的感官不符,于是决定先查看 redis 对于删除操作的代码,找出关键点,再做试验进行验证。

筹备工作

  • 须要复用这篇文章中,应用过的数据构造方法和测试脚本代码。

代码剖析步骤

  • 在 server.c 中找到 redisCommandTable(命令表,redis 的所有命令都对应这张表中的一个回调函数),找到 del 命令对应的回调函数 delCommand。查看 delCommand 函数的代码内容如下:
  • void delCommand(client *c) {delGenericCommand(c,0);
    }
  • delCommand 持续只是单纯的调用了一个通用删除办法 delGenericCommand,持续追踪 delGenericCommand,代码如下:
  • /* 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]);
          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++;
          }
      }
      addReplyLongLong(c,numdel);
    }
  • 该办法就比拟有意思了,首先正文就说这个命令实现了删除和懒删除(也就是咱们想要的异步删除)。再看此行代码:
  • int deleted  = lazy ? dbAsyncDelete(c->db,c->argv[j]) :
                                dbSyncDelete(c->db,c->argv[j]);
  • 也就是说依据参数 lazy 的不同而调用异步删除或同步删除。那么那里调用了这个办法,传递了什么参数呢?依据 ide 的追踪,发现有 2 个函数调用了以后函数,且 lazy 参数一个传 0,一个传 1,刚好对应了一个同步,一个异步。
  • void delCommand(client *c) {delGenericCommand(c,0);
    }
    
    void unlinkCommand(client *c) {delGenericCommand(c,1);
    }
  • 其中,delCommand 是 del 命令的回调,unlinkCommand 是 unlink 命令的回调。这就阐明 unlink 命令才会让 redis 采纳异步删除的形式。

试验验证

  • 结构数据和测试 php 脚本请参考这篇文章。
  • 首先采纳 redis-cli –pipe 的形式向 redis 增加一个 key 为 sigkey 的 hash 数据,其 hlen 为 3000 万,占用内存约 1.8G。
  • 向 redis 增加一个 key 为 m 的 string 类型数据,用于测试获取。
  • 应用 redis-cli 连贯 redis。
  • 开启测试 php 脚本。
  • redis-cli 中执行命令 unlink ligkey。
  • 敞开观测 php 脚本,观测后果。

试验后果

  • 有呈现标记信号的输入如下:
  • 0.57013500 1643333929--$4
    mack
    -------------------xxx---------------------
    0.70107700 1643333929--$4
    mack
    0.80816900 1643333929--$4
    mack
    0.92466400 1643333929--$4
    mack
    0.03091900 1643333930--$4
    mack
    0.13540800 1643333930--$4
    mack
    0.23995700 1643333930--$4
    mack
    0.34635700 1643333930--$4
    mack
    0.45889300 1643333930--$4
    mack
    0.56787100 1643333930--$4
    mack
    -------------------xxx---------------------
    0.69811500 1643333930--$4
    mack
    
  • 能够看到呈现稳定的两次距离均与 0.13 秒相差不大,且呈现这两个稳定的工夫节点与执行删除命令不同(执行命令的时候观测并未呈现标记),能够确认为失常网络稳定,排除 unlink 阻塞影响。

总结

  • 依据源码剖析及理论试验操作可得,del 命令应用同步删除,unlink 应用异步删除。
  • 在删除数据体量很小的简略类型时倡议应用 del 命令,在删除大 key 时应该应用 unlink 命令。
  • 删除小 key 应用 del 的起因是:尽管 del 是同步删除,会阻塞主线程,然而 unlink 同样会在主线程执行一些判断和其它操作。而这些操作可能带来的开销比理论删除一个小 key 还略大。所以能间接删的 key 就没必要应用异步删除了。
退出移动版