Redis 篇-深入了解 Redis 中的 RESP 通信协议与内存回收(过期 key 处理、内存淘汰策略)

🔥博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞👍收藏⭐评论✍

文章目录

        1.0 Redis 通信协议 - RESP 协议

        2.0 Redis 内存回收

        2.1 Redis 内存回收 - 过期 key 处理

        2.1.1 Redis 是如何知道一个 Key 是否过期呢?

        2.1.2 是不是 TTL 到期就立即删除了呢?

        2.2 Redis 内存回收 - 内存淘汰策略

        2.2.1 Redis 八种不同删除 key 的策略

        2.2.2 Redis 内存淘汰的流程图


        1.0 Redis 通信协议 - RESP 协议

        简单来说,通信协议就是对于发送命令或者接收命令格式的规范。

        Redis 是一个 CS 架构的软件,通信一般分两步:

        1)客户端向服务端发送一条命令

        2)服务端解析并执行命令,返回响应结果给客户端。

        1.1 RESP 协议 - 数据类型

        在 RESP 中,通过首字节的字符来区分不同数据类型,常用的数据类型包括 5 种:

        1)单行字符串:首字节是 "+",后面跟上单行字符串,以 CRLF("\r\n") 结尾。

举个例子:

        比如说要发送命令的格式:"+OK\r\n"。但需要注意的是,使用单行字符串发送命令,可能会导致二进制不安全问题发生。

        2)错误(Errors):首字节是 "-",与单行字符串格式一样,只是字符串是异常信息。

举个例子:

        服务端发送错误信息的格式:"-Error message\r\n" 。

        3)数值:首字节是 ":",后面跟上数字格式的字符串,以 CRLF 结尾。

举个例子:

        给服务端发送数值信息的格式:":10\r\n" 。

        4)多行字符串:首字节是 "$",表示二进制安全的字符串,最大支持 512 MB。

举个例子:

        给服务端发送多行字符串的格式:"$5\r\nhello\r\n"

需要注意的是: 

                如果大小为 0,则代表空字符串:"$0\r\n\r\n";

                如果大小为 -1,则代表不存在:"$-1\r\n";

        5)数组:首字节是 "*",后面跟上数组元素个数,再跟上元素,元素数据类型不限。

举个例子:

        给 Redis 服务端发送 "set name 童童" 的命令的格式:

        *3\r\n

        $3\r\nset\r\n

        $4\r\nname\r\n

        $6\r\n童童\r\n

字段解析:

        *3\r\n:表示的数组中有三个元素;

        $3\r\nset\r\n:数组的第一个元素是多行字符串类型,值为 set ,字节数为 3 个字节;

        $4\r\nname\r\n:数组的第二个元素也是多行字符串类型,值为 name ,字节数为 4 个字节;

        $6\r\n童童\r\n:数组的第三个元素也是多行字符串类型,值为 童童,字节数为 6 个字节;

        2.0 Redis 内存回收

        Redis 之所以性能强,最主要的原因就是基于内存存储。然而单节点的 Redis 其内存大小不宜过大,会影响持久化或主从同步性能。

        可以通过修改配置文件来设置 Redis 的最大内存:

        当内存使用达到上限时,就无法存储更多的数据了。因此,需要采用某些手段来解决内存达到上限的问题。

        一般可以通过内存回收来解决:过期 key 处理、内存淘汰机制。

        2.1 Redis 内存回收 - 过期 key 处理

        通过两个具体的问题来了解过期 Key 处理机制来解决内存不足:

        2.1.1 Redis 是如何知道一个 Key 是否过期呢?

        Redis 本身是一个典型的 key-value 内存存储数据库,因此所有的 key、value 都保存在 Dict 结构中。不过在 database 结构体中,有两个 Dict:一个用来记录 key-value;另一个用来记录 key-TTL 。

相关源码如下:

        解析其中最重要的两个字段:

        1)dict *dict:存放所有 key 及 value 的地方,也被称为 keyspace。

        2)dict *expires:存放每一个 key 及其对应的 TTL 存活时间,只包含设置 TTL 的 Key 。

相关的结构如下:

        所以,回到之前的问题:Redis 是如何知道一个 key 是否过期的?

        答案是利用两个 Dict 分别记录 Key-Value 以及 Key-TTL ,通过查询两个 Dict 来判断当前 key 是否过期的。

        2.1.2 是不是 TTL 到期就立即删除了呢?

        具体来说,Redis 处理过期 key 的方式一般来说有两种:惰性删除、周期删除。

        1)对于惰性删除来说:

        当你尝试访问一个 key 时,Redis 会检查该 key 是否已经过期。如果过期了,Redis 会将其删除并返回空值。这种方式被称为惰性删除。

相关的源码:

        2)对于周期删除来说:

        顾名思义,是通过一个定时任务,周期性的抽样部分过期的 key,然后执行删除。执行周期有两种:

        第一种:Redis 会设置一个定时任务 serverCron(),按照 server.hz 的频率来执行过期 key 清理,模式为 SLOW 。

SLOW 模式规则:

        执行频率受 server.hz 的影响,默认为 10,即每秒执行 10 次,每个执行周期 100ms 。

        执行清理耗时不超过一次执行周期的 25% 。

        逐个遍历 db,逐个遍历 db 中的 bucket,抽取 20 个 Key 判断是否过期。

        如果没达到时间上限(25 ms)并且过期 key 比例大于 10%,再进行一次抽样,否则结束。

        第二种:Redis 的每个事件循环前会调用 beforeSlepp() 函数,执行过期 key 清理,模式为 FAST 。

FAST 模式规则:

        执行频率受 beforeSleep() 调用频率影响,但两次 FAST 模式间隔不低于 2 ms 。

        执行清理耗时不超过 1ms 。

        逐个遍历 db,逐个遍历 db 中的 bucket,抽取 20 个 Key 判断是否过期。

        如果没达到时间上限(1 ms)并且过期 Key 比例大于 10%,再进行一次抽样,否则结束。

小结:

        1)RedisKey 的 TTL 记录方式:

        在 RedisDB 中通过一个 Dict 记录每个 key 的 TTL 时间。

        2)过期 key 的删除策略:

        惰性删除:每次查找 key 是判断是否过期,如果过期则删除;

        定期删除:定期抽样部分 key,判断是否过期,如果过期则删除。

        3)定期清理的两种模式:

        SLOW模式执行频率默认为每秒十次,每次不超过 25 ms 。

        FAST 模式执行频率不固定,但两次间隔不低于 2 ms,每次耗时不超过 1 ms 。

        2.2 Redis 内存回收 - 内存淘汰策略

        内存淘汰就是当 Redis 内存使用达到设置的阈值时,Redis 主动挑选部分 Key 删除从而来释放更多内存的流程。

        Redis 会在处理客户端命令的方法之前,先执行 processCommand() 中尝试做内存淘汰。

相关的源码:

        2.2.1 Redis 八种不同删除 key 的策略

        在配置文件中进行配置不同删除 key 的策略:

Redis 支持 8 种不同策略来选择要删除的 key:

        1)noeviction:不淘汰任何 key,但是内存满时不允许写入新数据,默认就是这种策略。

        2)volatile-ttl:对设置了 TTL 的 key,比较 key 的剩余 TTL 值,TTL 越小越先被淘汰。

        3)allkeys-random:对全体 key,随机进行淘汰。也就是直接从 db->dict 中随机挑选。

        4)volatile-random:对设置了 TTL 的 key,随机进行淘汰。也就是从 db->expires 中随机挑选。

        5)allkeys-lru:对全体 key,基于 LRU 算法进行淘汰。

        6)volatile-lru:对设置了 TTL 的 key,基于 LRU 算法进行淘汰。

        7)allkeys-lfu:对全体 key,基于 LFU 算法进行淘汰。

        8)volatile-lfu:对设置了 TTL 的 key,基于 LFU 算法进行淘汰。

LRU 算法:

        最少最近使用,用当前时间减去最后一次访问的时间,这个值越大则淘汰优先级越高。以秒为单位记录最近一次访问的时间,长度为 24 bit 。

LFU 算法:

        最少频率使用,会统计每个 key 的访问频率,值越小淘汰优先级越高。高 16 位以分钟为单位记录最近一次访问时间,低 8 位记录逻辑访问次数。

        2.2.2 Redis 内存淘汰的流程图

具体流程分析:

        在执行客户端发送过来的命令之前,先判断当前内存是否充足,如果内存还是很充足,那么不需要去执行删除 key 的操作。

        如果当前内存不充足时,继续判断内存策略是否为默认 noeviction 策略,也就是即使内存满了,也不会执行删除 key 的操作,会发出错误信息。

        假设不是默认策略,接着继续判断是从 dict 字典还是从 entries 字典中删除 key,该两者的区别就是有无设置 TTL。

        再紧接着,选择删除策略,假设选择了 random 策略,也就是随机选择 key 来删除。删除完之后,再判断内存是否充足,如果还是不足,那么会接着循环来删除 key,如果达到充足的内存,则直接退出删除 key 的操作。

        若选择的删除策略为:TTL、LRU、LFU 这些策略,先创建一个池,用来存放准备删除的 key,在 Redis 数据库中从 0 直到 15 的数据库进行遍历抽样选择要放入池中的 key,默认每次抽样 5 个 key。

        再接下来,根据具体选择的策略来进行将抽样 5 个 key 放入池中,每一个放入池中的 key 都以升序的方式进行排序。

        最后,将池中要确定删除的 key 进行删除,循环往复,直到内存充足为止。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/884835.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GESP等级考试C++二级-数学函数

C的cmath库中有丰富的数学函数,通过这些函数可以进行相应的数学计算。 1 cmath库的导入 通过import指令导入cmath库,代码如图1所示。 图1 导入cmath库的代码 2 abs()函数 abs()函数用来获取指定数的绝对值,代码如图2所示。 图2 abs()函数…

X86下一文带你构建Apollo9.0运行环境(基于Ubuntu20.04避坑版)

X86下一文带你构建Apollo9.0运行环境基于Ubuntu20.04避坑版 前言准备安装基础软件1.安装Docker19.03安装Nvidia驱动安装配置Nvidia container toolkit 下载Apollo源码(笔者下载的是releases下9.0.0版本,大家可以参考)编译Apollo9.0下载资源包…

vue-cli,element-plus,axios,proxy

一、vue-cli vue-cli俗称vue脚手架,是vue官方提供的快速生成vue 工程化项目的工具。 1.官网:https://cn.vuejs.org/ 中文官网: https://cli.vuejs.org/zh/ 特点:基于webpack,功能丰富且易于扩展,支持创建vue2和vu…

对话总结:Scale AI的创始人兼CEO Alex Wang

AI的三大支柱 计算:主要由大公司如NVIDIA推动。算法:顶尖实验室如OpenAI主导。数据:Scale致力于推动数据进展。前沿数据的重要性 与人类智能相比较,前沿数据是AI发展的关键。互联网数据是机器与人类合作的结果。语言模型的发展 第一阶段:原始的Transformer论文和GPT的小规…

一书直接讲透自然语言处理《Getting Started with Google BERT_ Build and train》

《Getting Started with Google BERT: Build and Train》是一本面向初学者和中级读者的指南,旨在帮助他们理解和使用Google的BERT(Bidirectional Encoder Representations from Transformers)模型。BERT是近年来自然语言处理(NLP&…

Linux下的git开篇第一文:git的意义

目录 1.git版本控制器 2.git gitee&&github 3.Linux中gitee的使用 ( 三板斧 git add git commit -m " " git push ) 4.git log 查看之前的修改信息 (所有提交日志) 5.git status 查看工作目录与本地…

透传 vs 非透传|数据传输效率与安全性的权衡及应用指南

官方原文:一分钟搞懂透传和非透传的区别-成都纵横指控 在当今数字化时代,数据传输已经成为各行各业的关键环节。在数据通信和物联网应用中,"透传"和"非透传"是两个常见且重要的概念。了解它们的区别,对于选择合适的通信方式至关重要。 什么是…

【java】前端RSA加密后端解密

目录 1. 说明2. 前端示例3. 后端示例3.1 pom依赖3.2 后端结构图3.3 DecryptHttpInputMessage3.4 ApiCryptoProperties3.5 TestController3.6 ApiCryptoUtil3.7 ApiDecryptParamResolver3.8 ApiDecryptRequestBodyAdvice3.9 ApiDecryptRsa3.10 ApiCryptoProperties3.11 KeyPair3…

C++(Qt)软件调试---内存调试器Dr.Memory(21)

C(Qt)软件调试—内存调试器Dr. Memory(21) 文章目录 C(Qt)软件调试---内存调试器Dr. Memory(21)[toc]1、概述🐜2、安装Dr.Memory🪲3、命令行使用Dr.Memory🦗4、Qt Creator集成使用Dr.Memory&…

excel快速入门(二)

Excel的概念说明 文章目录 Excel的概念说明常见术语说明单元格/单元格区域活动单元格/单元格区域行或列单元格引用相对引用绝对引用混合引用 Excel的常见格式说明单元格格式数字格式 Excel 工作表编辑鼠标指针介绍1.白色十字状2.单向黑色箭头状3.双向单竖线箭头状4.双向双竖线箭…

AI新掌舵:智享AI直播系统:直播界的新浪潮还是真人主播的终结者?

AI新掌舵:智享AI直播系统:直播界的新浪潮还是真人主播的终结者? 在数字化浪潮的汹涌澎湃中,人工智能(AI)以其前所未有的速度渗透至各行各业,其中,直播领域正经历着一场前所未有的变革…

C# CS1612 尝试修改集合中值类型的情况

在C#中,发现尝试直接修改集合中值类型的中的值发生报错 提示“它不是变量”,通过官方索引的链接可知,尝试修改某一值类型,但是该值类型作为中间表达式的结果生成但不存储在变量中,会发生报错。 正确做法是将其赋值给局…

【湖南步联科技身份证】 身份证读取与酒店收银系统源码整合———未来之窗行业应用跨平台架构

一、html5 <!DOCTYPE html> <html><head><meta http-equiv"Content-Type" content"text/html; charsetutf-8" /><script type"text/javascript" src"http://51.onelink.ynwlzc.net/o2o/tpl/Merchant/static/js…

nginx 安装(Centos)

nginx 安装-适用于 Centos 7.x [rootiZhp35weqb4z7gvuh357fbZ ~]# lsb_release -a LSB Version: :core-4.1-amd64:core-4.1-noarch Distributor ID: CentOS Description: CentOS Linux release 7.9.2009 (Core) Release: 7.9.2009 Codename: Core# 创建文件…

基于springboot vue网上摄影工作室系统设计与实现

博主介绍&#xff1a;专注于Java vue .net php phython 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟 我的博客空间发布了1000毕设题目 方便大家学习使用 感兴趣的…

04 面部表情识别:Pytorch实现表情识别-表情数据集训练代码

总目录&#xff1a;人脸检测与表情分类 https://blog.csdn.net/whiffeyf/category_12793480.html 目录 0 相关资料1 面部表情识数据集2 模型下载3 训练 0 相关资料 面部表情识别2&#xff1a;Pytorch实现表情识别(含表情识别数据集和训练代码)&#xff1a;https://blog.csdn.n…

Linux系统安装和配置 VNC 服务器

文章目录 1.安装 GNOME 桌面环境2.安装 VNC 服务器&#xff08;tigervnc-server&#xff09;3.为本地用户设置 VNC 密码4.设置 VNC 服务器配置文件5.启动 VNC 服务并允许防火墙中的端口 1.安装 GNOME 桌面环境 [rootserver6 ~]# dnf groupinstall "workstation" -y成…

Linux——k8s组件

kubernetes 使用1.31.1 版本搭建集群核心组件&#xff0c;选择flannel 网络插件为整体集群的运行提供网络通信功能。 flannel 网络插件 kube-flannel kube-flannel-ds-9fgml 1/1 Running 1 (18m ago) 2d21h kube-flannel kube-flannel-ds-ghwbq …

blender设置背景图怎么添加?blender云渲染选择

Blender是一款功能强大的3D建模软件&#xff0c;它以流畅的操作体验和直观的用户界面而闻名。使用Blender&#xff0c;你可以轻松地为你的3D模型添加背景图片。 以下是具体的操作步骤&#xff1a; 1、启动Blender&#xff1a;首先&#xff0c;打开Blender软件。访问添加菜单&a…

jQuery——offset 和 position

获取/设置标签的位置数据 offset&#xff08;&#xff09;&#xff1a;相对页面左上角的坐标 position&#xff08;&#xff09;&#xff1a;相对于父元素左上角的坐标 本文分享到此结束&#xff0c;欢迎大家评论区相互讨论学习&#xff0c;下一篇继续分享jQuery中scroll的学…