Redis lazy free 机制分析

it2023-05-31  109

目录

Lazy Free要解决的问题

Lazy Free的官方简介

问题分析

Lazy Free的静态结构

Lazy Free的配置定义

Lazy Free的流程分析


Lazy Free要解决的问题

Lazy Free的官方简介

首先,我们来看看官方给出的,关于这个新特性的简介:

* Lazy freeing of keys. Redis is now able to delete keys in the background in a different thread without blocking the server. The new `UNLINK` command is the same as `DEL` but working in a non blocking way. Similarly an `ASYNC` option was added to `FLUSHALL` and `FLUSHDB` in order to let the entire dataset or a single database to be freed asynchronously.

可以很轻易地抓到这段描述中的重点:blocking the server

这里就引出了一个值得讨论的问题:为什么删除key会导致Redis服务阻塞?

问题分析

首先,我们讨论Redis如何存储KV对。

这里直接把redisDb结构体的定义和《Redis设计与实现》中的贴出来,可以看到KV对直接存储在一个dict,即字典中。

/* Redis database representation. There are multiple databases identified * by integers from 0 (the default database) up to the max configured * database. The database number is the 'id' field in the structure. */ typedef struct redisDb { dict *dict; /* The keyspace for this DB */ dict *expires; /* Timeout of keys with a timeout set */ dict *blocking_keys; /* Keys with clients waiting for data (BLPOP)*/ dict *ready_keys; /* Blocked keys that received a PUSH */ dict *watched_keys; /* WATCHED keys for MULTI/EXEC CAS */ int id; /* Database ID */ long long avg_ttl; /* Average TTL, just for stats */ unsigned long expires_cursor; /* Cursor of the active expire cycle. */ list *defrag_later; /* List of key names to attempt to defrag one by one, gradually. */ } redisDb;

也就是说,Redis对KV的CURD操作,底层实现能追溯到dict的相关代码。最后我们可以发现对于val,我们是将其转化为一个list结构体进行释放。在引入Lazy Free机制之前,删除一个大Key必然导致Redis的主进程卡死。

这里附上一部分的源码分析,从删除的入口函数一路往下跟,最后可以发现调用的是dictListDestructor函数。

void dictListDestructor(void *privdata, void *val) { DICT_NOTUSED(privdata); listRelease((list*)val); }

Lazy Free的静态结构

如图所示,lazy free这个模块其实可以视为一个中间层:

北向暴露2个接口,分别用于查询队列中等待删除的任务数量和触发删除;北向对接的其他模块此处不展开,用一个Redis Server代替。

南向需要后台进程管理模块提供一个入队接口,需要集群模块和字典模块提供一些实际的删除接口,即针对这种特定的数据结构的删除方法;同时向进程管理模块暴露一个删除的wrapper,其实就是集群模块和字典模块提供的删除接口的wrapper。

Lazy Free的配置定义

名称作用默认值取值范围

lazyfree-lazy-eviction

内存占用过高时发生的驱逐是否使用lazy freenoyes|no

lazyfree-lazy-expire

过期键的删除是否使用lazy freenoyes|no

lazyfree-lazy-server-del

其他命令或机制引起的删除(即Redis自身触发的删除)是否使用lazy freenoyes|no

replica-lazy-flush

主从同步时,从库触发全量同步时的删库是否使用lazy freenoyes|no

lazyfree-lazy-user-del

是否将用户发起的删除全部视为lazy free处理noyes|no

Lazy Free的流程分析

lazy free的主要流程如上图所示

最新回复(0)