百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

「每天一道面试题」Redis过期策略及实现原理

wptr33 2024-12-17 16:47 14 浏览

Redis过期策略及实现原理

描述

我们在使用 Redis 时,一般会设置一个过期时间,当然也有不设置过期时间的,也就是永久不过期。当我们设置了过期时间,Redis 是如何判断是否过期,以及根据什么策略来进行删除的。

redis过期时间设置

语法

# 以秒为单位设置过期,这是最常用的方式
EXPIRE KEY time

# 字符串独有的方式
SETEX KEY_NAME TIMEOUT VALUE

说明

除了 字符串 自己独有设置过期时间的方法外,其他方法都需要依靠 EXPIRE 方法来设置时间,如果没有设置时间,那缓存就是永不过期。

如果设置了过期时间,之后又想让缓存永不过期,使用 persist KEY

三种过期策略

定时删除

含义

在设置 KEY 的过期时间的同时,为该 KEY 创建一个定时器,让定时器在 KEY 的过期时间来临时,对 KEY 进行删除。

优点

该方法可以保证内存被尽快释放。

缺点

若过期 KEY 很多,删除这些 KEY 会占用很多的 CPU 时间,在 CPU 时间紧张的情况下,CPU 不能把所有的时间用来做要紧的事儿,还需要去花时间删除这些 KEY。

定时器的创建耗时,若为每一个设置过期时间的 KEY 创建一个定时器(将会有大量的定时器产生),性能影响严重。

懒汉式删除

含义

KEY 过期的时候不删除,每次通过 KEY 获取值的时候去检查是否过期,若过期,则删除,返回 null。

优点

删除操作只发生在通过 KEY 取值的时候,而且只删除当前 KEY,所以对 CPU 时间的占用是比较少的,而且此时的删除是已经到了非做不可的地步(如果此时还不删除的话,我们就会获取到了已经过期的 KEY 了)。

缺点

若大量的 KEY 在超出超时时间后,很久一段时间内,都没有被获取过,那么可能发生内存泄露(无用的垃圾占用了大量的内存)。

定期删除

含义

每隔一段时间执行一次删除过期 KEY 操作。

优点

通过限制删除操作的时长和频率,来减少删除操作对 CPU 时间的占用。

缺点

在内存友好方面,不如 ”定时删除”(会造成一定的内存占用,但是没有懒汉式那么占用内存),在 CPU 时间友好方面,不如 ”懒汉式删除”(会定期的去进行比较和删除操作,cpu 方面不如懒汉式,但是比定时好)。

难点是合理设置删除操作的执行时长(每次删除执行多长时间)和执行频率(每隔多长时间做一次删除)(这个要根据服务器运行情况来定了),每次执行时间太长,或者执行频率太高对 cpu 都是一种压力。每次进行定期删除操作执行之后,需要记录遍历循环到了哪个标志位,以便下一次定期时间来时,从上次位置开始进行循环遍历。

说明

memcached 只是用了惰性删除,而 redis 同时使用了惰性删除与定期删除,这也是二者的一个不同点(可以看做是 redis 优于 memcached 的一点)。

对于懒汉式删除而言,并不是只有获取 KEY 的时候才会检查 KEY 是否过期,在某些设置 KEY 的方法上也会检查,比如 SETNEX 命令,因为 SETNX 命令是在 KEY 不存在的情况下才设置,因为,如果不做过期 KEY 检查,那么直接设置,就会与我们原来的意思相违背。

定时任务

单线程的 redis,如何知道要运行定时任务?

redis 是单线程的,线程不但要处理定时任务,还要处理客户端请求,线程不能阻塞在定时任务或处理客户端请求上,那么,redis 是如何知道何时该运行定时任务的呢?

Redis 的定时任务会记录在一个称为最小堆的数据结构中。这个堆中,最快要执行的任务排在堆的最上方。在每个循环周期,Redis 都会将最小堆里面已经到点的任务立即进行处理。处理完毕后,将最快要执行的任务还需要的时间记录下来,这个时间就是接下来处理客户端请求的最大时长,若达到了该时长,则暂时不处理客户端请求而去运行定时任务。

配置

Redis 中定期删除使用的是统一的一个定时器,定时器执行的时长默认为 10,具体配置如下:



提高它的值将会占用更多的 cpu,当然相应的 redis 将会更快的处理同时到期的许多 key,以及更精确的去处理超时。 hz 的取值范围是 1~500,通常不建议超过 100,只有在请求延时非常低的情况下可以将值提升到 100。

Redis采用的过期策略

说明

Redis 采用的是懒汉式删除+定期删除。

懒汉式删除流程

  1. 在进行 GET 或 SETNX 等操作时,先检查 KEY 是否过期;
  2. 若过期,删除 KEY,然后执行相应操作;
  3. 若没过期,直接执行相应操作;

定期删除流程

简单而言,对指定 N 个库的每一个库随机删除小于等于指定 M 个过期 KEY,具体流程如下:

  1. 遍历每个数据库(就是 redis.conf 中配置的 ”database” 数量,默认为 16)
  2. 检查当前库中的指定个数个 KEY(默认是每个库检查 20 个 KEY,注意相当于该循环执行 20 次,循环体是下边的描述)
  3. 如果当前库中没有一个 KEY 设置了过期时间,直接执行下一个库的遍历随机
  4. 获取一个设置了过期时间的 KEY,检查该 KEY 是否过期,如果过期,删除 KEY 判断定期删除操作是否已经达到指定时长,若已经达到,直接退出定期删除。

对于定期删除,在程序中有一个全局变量 current_db 来记录下一个将要遍历的库,假设有 16 个库,我们这一次定期删除遍历了 10 个,那此时的 current_db 就是 11,下一次定期删除就从第 11 个库开始遍历,假设 current_db 等于 15 了,那么之后遍历就再从 0 号库开始(此时 current_db==0)。

参考文章:嗨客网 Redis 过期策略及实现原理

相关推荐

Linux高性能服务器设计

C10K和C10M计算机领域的很多技术都是需求推动的,上世纪90年代,由于互联网的飞速发展,网络服务器无法支撑快速增长的用户规模。1999年,DanKegel提出了著名的C10问题:一台服务器上同时...

独立游戏开发者常犯的十大错误

...

学C了一头雾水该咋办?

学C了一头雾水该怎么办?最简单的方法就是你再学一遍呗。俗话说熟能生巧,铁杵也能磨成针。但是一味的为学而学,这个好像没什么卵用。为什么学了还是一头雾水,重点就在这,找出为什么会这个样子?1、概念理解不深...

C++基础语法梳理:inline 内联函数!虚函数可以是内联函数吗?

上节我们分析了C++基础语法的const,static以及this指针,那么这节内容我们来看一下inline内联函数吧!inline内联函数...

C语言实战小游戏:井字棋(三子棋)大战!文内含有源码

井字棋是黑白棋的一种。井字棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉、一条龙、三子旗等。将正方形对角线连起来,相对两边依次摆上三个双方棋子,只要将自己的三个棋子走成一条线,对方就算输了。但是,有很多时...

C++语言到底是不是C语言的超集之一

C与C++两个关系亲密的编程语言,它们本质上是两中语言,只是C++语言设计时要求尽可能的兼容C语言特性,因此C语言中99%以上的功能都可以使用C++完成。本文探讨那些存在于C语言中的特性,但是在C++...

在C++中,如何避免出现Bug?

C++中的主要问题之一是存在大量行为未定义或对程序员来说意外的构造。我们在使用静态分析器检查各种项目时经常会遇到这些问题。但正如我们所知,最佳做法是在编译阶段尽早检测错误。让我们来看看现代C++中的一...

ESL-通过事件控制FreeSWITCH

通过事件提供的最底层控制机制,允许我们有效地利用工具箱,适时选择使用其中的单个工具。FreeSWITCH是一个核心交换与混合矩阵,它周围有几十个模块提供各种功能特性。我们完全控制了所有的即时信息,这些...

物理老师教你学C++语言(中篇)

一、条件语句与实验判断...

C语言入门指南

当然!以下是关于C语言入门编程的基础介绍和入门建议,希望能帮你顺利起步:C语言入门指南...

C++选择结构,让程序自动进行决策

什么是选择结构?正常的程序都是从上至下顺序执行,这就是顺序结构...

C++特性使用建议

1.引用参数使用引用替代指针且所有不变的引用参数必须加上const。在C语言中,如果函数需要修改变量的值,参数必须为指针,如...

C++程序员学习Zig指南(中篇)

1.复合数据类型结构体与方法的对比C++类:...

研一自学C++啃得动吗?

研一自学C++啃得动吗?在开始前我有一些资料,是我根据网友给的问题精心整理了一份「C++的资料从专业入门到高级教程」,点个关注在评论区回复“888”之后私信回复“888”,全部无偿共享给大家!!!个人...

C++关键字介绍

下表列出了C++中的常用关键字,这些关键字不能作为变量名或其他标识符名称。1、autoC++11的auto用于表示变量的自动类型推断。即在声明变量的时候,根据变量初始值的类型自动为此变量选择匹配的...