Redis命令DEL与UNLINK的区别,如何正确删除大Key!

马尔科夫尼可夫 -
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就没必要使用异步删除了。
特别申明:本文内容来源网络,版权归原作者所有,如有侵权请立即与我们联系(cy198701067573@163.com),我们将及时处理。

php介绍

PHP即“超文本预处理器”,是一种通用开源脚本语言。PHP是在服务器端执行的脚本语言,与C语言类似,是常用的网站编程语言。PHP独特的语法混合了C、Java、Perl以及 PHP 自创的语法。利于学习,使用广泛,主要适用于Web开发领域。

Tags 标签

cphpredis

扩展阅读

加个好友,技术交流

1628738909466805.jpg