引言
Redis 是一款高性能的内存数据库,被广泛用于缓存、消息队列、排行榜等场景。在 Redis 中,键的过期时间是一项重要功能,通过设置键值对的过期时间可以有效防止缓存数据过期后数据淘汰问题的发生,同时也可以优化内存的使用。
然而,Redis 并不是像其他的内存数据库一样会及时地将过期的键值对删除或者放入数据淘汰算法池中,而是采用惰性删除(Lazy Deletion)和定期删除(Active Expire)相结合的方式来保证过期键的删除。在本篇文章中,我们将详细介绍 Redis 过期键清理的原理和实现方法。
Redis 过期键清理的原理
Redis 通过每秒钟执行一次的定期删除和惰性删除两种方式来清理过期键。
定期删除
定期删除是 Redis 中过期键清理的一种机制。Redis 会每秒钟检查一定比例的过期键是否需要删除,这个比例由配置文件中的 hz
参数控制,默认值为 10
。这个参数的含义是每秒钟执行的定时任务的数量。当 hz
参数被设置为 10
时,每秒钟会执行 10
次定时任务,也就是说每 100ms
执行一次。
Redis 对每个数据库都会维护一个过期字典来存储该数据库中所有的过期键。在每次定时任务执行时,Redis 会随机取出一定比例(由配置文件中的 maxmemory-samples
参数控制)的键值对,然后检查它们的过期时间是否已经过期。如果过期了,就将其从数据库中删除。
定期删除虽然能够自动删除过期键,但是它是一种被动的删除方式。用户不能精确地知道哪一个过期键会在下一次定期任务执行被删除,也不能针对性地增加删除比例,从而达到更好的删除效率。
惰性删除
惰性删除是 Redis 中过期键清理的另一种机制。当客户端访问一个已经过期的键值对时,Redis 会判断这个键值对是否已经过期。如果过期了,就将其删除。因此,惰性删除是一种主动的过期键清理方式,能够精准地删除过期的键值对。
但是,惰性删除也有其缺点。当一个键值对已经过期时,如果客户端不再访问该键值对,那么它将一直保留在数据库中消耗内存,直到下一次定期任务执行或者其他的惰性删除操作发生。
综合来讲,Redis 的过期键清理机制是通过定期删除和惰性删除相结合的方式来完成过期键的删除。定期删除是一种被动的过期键清理方式,惰性删除是一种主动的过期键清理方式。两种方式相结合可以保证 Redis 在满足高并发的同时,又能够高效地清理过期键值对,从而避免因为内存不足而导致 Redis 无法工作的情况发生。
Redis 过期键清理的实现
Redis 的过期键清理机制是通过懒汉式(Lazy Loading)的方式来实现的。懒汉式是一种典型的性能优化策略,它采用按需加载的方式来减少不必要的资源消耗,从而达到更高的性能效果。
在 Redis 中,当一个键值对设置了过期时间时,Redis 会将其添加到过期字典中,然后将该键值对添加到相应的数据库中。在后续的访问中,Redis 会对访问的键值对进行检查,如果发现该键值对已经过期,则删除该键值对并从过期字典中删除该键值对。
具体的实现细节如下:
定期删除
定期删除的实现非常简单,Redis 在启动时会启动一个线程来执行一些后台任务,其中就包括定期删除任务。定期删除的任务代码如下:
------ ---- ----------------------- - ----- ------------------------------ - ---- ---- --- - --------- --- -- -- -------------------------- - --- ---------- - -- --------- ---- -- ------------- -- --- ------------ - ----------- ------------------------------ -- -------- -- --- -- - -- - - ------------- ---- - -- ------------------ -- --------- - ----------------- - -- - ---- - ----------------- - --------------------- - ------------- - -- -------------- -- ------ ------- - ----------------------------------------- ------ --------- - -------------------------------------------- -- ----------- ------ ----------------------------------- -- -- ------ ----------------- - ---------------------------------------------------------------------------------------- ----------------- -- ------------------------------------------------------- - ----------------------------------------------------- - - - ----------------------------------------------------- ----------------- - -------- ------------------ - --------- - --------- - ------------------- -- ------------------ - -- ----------------- - -- -- ---------------------- -- -- ---------- -- -- --------- -- --------------------- -- ------------ --- - ------------------------------------------------------- --------- ---- -- ------------ -- --------- - ------------- -- ----- - ---- ---- - --------------- ---- ---- -- -- ---------------- -- -- --- - -------------------------------------------- -- --- --------- -- --------------------- -- -- ---- - -- - -------------------------- ------------------------------------------------------------------- ------------------------------------------ -- ----------------------------- ------------------------------------ -------------------- -- ------------- -- -- -- ------------------------------------------- - ----- ------ - -- --------------------------------------- -- -- ------------------ -- -- ------ - -- ------- -- ------------------------ - - --------------------------------- ---- ---- ----- - ------------- -- ------ - --------------- - ------------------------------- - - -
该函数每秒钟被执行的次数是通过 config.h 文件中的 config_hz
宏来指定的,默认是 10
。
惰性删除
惰性删除是在对 Key 进行读、写等操作的时候进行的。 Redis 实现惰性删除是依靠 Redis 的多态字符串(sdstr)实现。当系统计算哈希值时,系统同时会判断当前 Key 是否过期,如果过期了,就会被移除。因此,惰性删除不需要在 redis 中设置定时任务进行操作。
Redis 过期键清理的实例
添加过期键
添加过期键的方法就是 setex
,示例如下:
----- ----- - -------
这里设置了一个 5 秒钟的过期时间。
获取键值对
获取键值对的方法就是 get
,示例如下:
--- -----
演示效果
我们可以通过以上的命令来对 Redis 中的键值对进行操作。在执行完 setex
命令之后,我们可以使用 get
命令来查看键值对是否有效,当过期时间到达时,再次执行 get
命令就会发现该键值对已经被删除。
总结
Redis 的过期键清理机制采用了懒汉式的思想,通过惰性删除和定期删除两种方式相结合的方式来清理过期键值对。惰性删除主动,可以保证过期键的及时删除,但是需要等待到第一次访问的时候才能被删除,而定期删除被动,可以在一定程度上减少内存的占用,降低 Redis 的运行开销。
我们在实际开发中,如果需要使用 Redis 来缓存数据,就需要根据实际的业务场景和业务需求对过期键的删除机制进行合理的调整,以达到最好的效果。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6651f65bd3423812e46536ec