Redis源码中异步删除各参数具体作用是什么?

摘要:以前对异步删除几个参数的作用比较模糊,包括网上的很多资料都是一笔带过,语焉不详。 所以这次从源码(基于 Redis 7.0.5)的角度来深入分析下这几个参数的具体作用: lazyfree-lazy-user-del lazyfree-laz
以前对异步删除几个参数的作用比较模糊,包括网上的很多资料都是一笔带过,语焉不详。 所以这次从源码(基于 Redis 7.0.5)的角度来深入分析下这几个参数的具体作用: lazyfree-lazy-user-del lazyfree-lazy-user-flush lazyfree-lazy-server-del lazyfree-lazy-expire lazyfree-lazy-eviction slave-lazy-flush lazyfree-lazy-user-del 在 Redis 4.0 之前,通常不建议直接使用 DEL 命令删除一个 KEY。这是因为,如果这个 KEY 是一个包含大量数据的大 KEY,那么这个删除操作就会阻塞主线程,导致 Redis 无法处理其他请求。这种情况下,一般是建议分而治之,即批量删除 KEY 中的元素。 在 Redis 4.0 中,引入了异步删除机制,包括一个新的命令 -UNLINK。该命令的作用同DEL一样,都用来删除 KEY。只不过DEL命令是在主线程中同步执行删除操作。而UNLINK命令则是通过后台线程异步执行删除操作,即使碰到一个大 KEY,也不会导致主线程被阻塞。 如果应用之前用的是DEL,要使用UNLINK,就意味着代码需要改造,而代码改造显然是个费时费力的事情。 为了解决这个痛点,在 Redis 6.0 中,引入了参数 lazyfree-lazy-user-del。将该参数设置为 yes(默认为 no),则通过DEL命令删除 KEY,效果同UNLINK一样,都是执行异步删除操作。 以下是DEL命令和UNLINK命令的实现代码。 //DEL命令调用的函数 voiddelCommand(client*c){ delGenericCommand(c,server.lazyfree_lazy_user_del); } //UNLINK命令调用的函数 voidunlinkCommand(client*c){ delGenericCommand(c,1); } 可以看到,当 server.lazyfree_lazy_user_del 设置为 yes 时,DEL命令实际上调用的就是 delGenericCommand(c,1),与UNLINK命令一样。 lazyfree-lazy-user-flush 在 Redis 中,如果要清除整个数据库的数据,可使用FLUSHALL(清除所有数据库的数据)或FLUSHDB(清除当前数据库的数据)。 在 Redis 4.0 之前,这两个命令都是在主线程中执行的。如果要清除的 KEY 比较多,同样会导致主线程被阻塞。 如果使用的是 Redis Cluster,在执行此类操作时,很容易会触发主从切换。 主要原因是在删除期间,主节点无法响应集群其它节点的心跳请求。如果没有响应持续的时间超过 cluster-node-timeout(默认15 秒),主节点就会被集群其它节点判定为故障,进而触发故障切换流程,将从节点提升为主节点。 这个时候,原主节点会降级为从节点,降级后,原主节点又会重新从新的主节点上同步数据。所以,虽然原主节点上执行了 FLUSH 操作,但发生故障切换后,数据又同步过来了。如果再对新的主节点执行 FLUSH 操作,同样会触发主从切换。 所以,在这种情况下,建议将参数 cluster-node-timeout 调整为一个比较大的值(默认是 15 秒),这样就可以确保主节点有充足的时间来执行 FLUSH 操作而不会触发切换流程。 在 Redis 4.0 中,FLUSHALL和FLUSHDB命令新增了一个 ASYNC 修饰符,可用来进行异步删除操作。如果不加 ASYNC,则还是主线程同步删除。 FLUSHALLASYNC FLUSHDBASYNC 在 Redis 6.2.0 中,FLUSHALL和FLUSHDB命令又新增了一个 SYNC 修饰符,它的效果与之前的FLUSHALL和FLUSHDB命令一样,都是用来进行同步删除操作。 既然效果一样,为什么要引入这个修饰符呢?这实际上与 Redis 6.2.0 中引入的 lazyfree-lazy-user-flush 参数有关。该参数控制了没有加修饰符的FLUSHALL和FLUSHDB命令的行为。 默认情况下,lazyfree-lazy-user-flush 的值为 no,这意味着 FLUSHALL/FLUSHDB 将执行同步删除操作。如果将 lazyfree-lazy-user-flush 设置为 yes,即使不加 ASYNC 修饰符,FLUSHALL/FLUSHDB 也会进行异步删除。
阅读全文