共计 2106 个字符,预计需要花费 6 分钟才能阅读完成。
背景
- 在这篇文章中做过应用 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 就没必要应用异步删除了。
正文完