Redis学习(四)Redis原理:底层数据结构、网络模型、内存回收策略

news2024/11/25 0:59:07

文章目录

  • Redis底层数据结构
    • SDS 动态字符串
    • IntSet 整数集合
    • Dict 字典
      • Dict伸缩中的渐进式再哈希
    • ZipList 压缩列表
    • QuickLisk 快速列表
    • SkipList 跳表
      • 动态索引建立
    • RedisObject
    • 变量类型与数据结构实现
      • String
      • List
      • Set
      • ZSet
      • Hash
  • Redis网络模型
    • Redis是单线程还是多线程?
      • 为什么Redis要选择单线程?
    • epoll事件通知模式
  • 内存回收策略
    • 过期策略
      • Redis是如果知道一个key是否过期?
      • 是不是TTL到期就立即删除了呢?
    • 淘汰策略
      • LRU与LFU

Redis底层数据结构

SDS 动态字符串

Redis自身构建了一种新的字符串结构,称为简单动态字符串,简称SDS。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

IntSet 整数集合

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Dict 字典

  • Dict由三部分组成,分别是:哈希表、哈希节点、字典。

  • 字典Dict包含两个哈希表,其中一个是当前数据,另一个一般为空,rehash时使用。

  • 哈希表中的每个节点是哈希节点,哈希节点类似于链表的节点。

在这里插入图片描述

在这里插入图片描述

Dict伸缩中的渐进式再哈希

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ZipList 压缩列表

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

QuickLisk 快速列表

ZipList虽然节省内存,但是申请内存必须是连续空间,如果内存占用较多,申请内存效率较低。

QuickList特点:

  • 是一个节点为ZipList的双端链表
  • 节点采用ZipList,解决了传统链表的内存占用问题
  • 控制了ZipList大小,解决连续内存空间申请效率问题。
  • 中间节点可以压缩,进一步节省了内存。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

SkipList 跳表

跳表是对原始链表的改进,原始链表查询每个节点都要进行O ( n ) O(n)O(n)的遍历,而跳表借鉴了二分查找的思路对链表的索引进行了分级处理,跳表本质是可以实现二分查找的有序链表。

SkipList的特点:

  • 跳表是一个双向链表,每个节点都包含score和ele,score类似index,而ele是实际存储的字符串内容,节点按照score值排序,score值一样则按照ele字典序排序。
  • 每个节点都可以包含多层指针,层数是1-32之间的随机数。
  • 不同指针到下一个节点的跨度不同,层级越高,跨度越大。
  • 增删改查效率与红黑树基本一致,实现却更简单。

在这里插入图片描述

在这里插入图片描述

动态索引建立

在已知数据分布的情况下,不断选择数据中点作为索引建立的位置是最理想的:
在这里插入图片描述
而实际中我们建立跳表的过程是一个个动态添加或者删除的。如一直往原始列表中添加数据,但是不更新索引,就可能出现两个索引节点之间数据非常多的情况,极端情况,跳表退化为单链表:
在这里插入图片描述

最理想的索引就是二分查找的情形,在原始链表(假设长度为n),随机选 n/2 个元素做为一级索引、随机选 n/4 个元素做为二级索引、随机选 n/8 个元素做为三级索引,依次类推,一直到最顶层索引。

跳表中采用randomLevel() 方法来实现上述索引建立过程,该方法会随机生成 1~MAX_LEVEL 之间的数(MAX_LEVEL表示索引的最高层数),且该方法有 1/2 的概率返回 1、1/4 的概率返回 2、1/8的概率返回 3,以此类推。(randomLevel()的实现可以是循环调用一个有0.5概率返回1的函数,如果是1,则继续调用该函数 ,直至为0。)

跳表实际上是使用了这种随机产生元素的索引高度的方式,来打乱了输入的规律性,使得整体上按索引查询某个元素的时间复杂度为O ( l o g N ) O(logN)O(logN)

假设新加入一个元素6,通过randomLevel()函数返回了1,即建立一层索引(一层索引只能建立在最下边的层),它的建立方式如下:
从表头节点的最高层索引出发,如果某个节点的下一个元素大于该插入元素(6),则停止,进入下一层索引,依次类推,直至当前层与元素(6)的索引层相同,将节点插入。
在这里插入图片描述

RedisObject

RedisObject是Redis中存放数据对象的实际类型。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

变量类型与数据结构实现

String

String类型的RedisObject中包含有很多头部信息,因此如果能够使用数值类型,尽量使用集合来保存,这样一个RedisObject中就能存放更多的元素。
在这里插入图片描述

List

3.2版本之前采用ZipList和LinkedList实现,3.2版本之后,统一采用QuickList实现。

在这里插入图片描述

Set

  • 为了查询效率和唯一性,Set使用Dict实现。
  • 当存储所有数据都是整数,可以采用IntSet编码实现。
    在这里插入图片描述

ZSet

ZSet(有序集合)是通过跳表(保证有序)和字典(保证查询是否存在的效率)这两种数据结构实现的:
在这里插入图片描述
但是当元素数量不多时,HT和SkipList优势不明显,ZSet会采用ZipList结构来节省内存:
在这里插入图片描述

Hash

在这里插入图片描述

Redis网络模型

Redis是单线程还是多线程?

  • 如果仅仅聊Redis的核心业务部分(命令处理),都是单线程的。
  • 如果聊整个Redis,就是多线程。

为什么Redis要选择单线程?

  • 抛开持久化不谈,Redis是纯内存操作,执行速度非常快,它的性能瓶颈是网络延迟而不是执行速度,因此多线程并不会带来巨大的性能提升。
  • 多线程会导致过多的线程上下文切换,带来不必要的开销。
  • 引入多线程会面临线程安全问题,必然要引入锁等保证线程安全的手段,实现复杂度高,且性能也会大打折扣。

epoll事件通知模式

在这里插入图片描述

内存回收策略

过期策略

Redis是如果知道一个key是否过期?

在这里插入图片描述
利用两个Dict分别记录key-value和key-TTL对,通知TTL,检测是否过期

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

不是,Redis采用了下面两种过期策略:

  • 惰性删除
  • 周期删除

惰性删除是在后期再次访问同一个key时,会检查key是否过期,如过期则删除。
在这里插入图片描述
惰性删除的方式下,对于已经过期但是后续没有访问的数据,会一直存活占用内存。这时候Redis又引入了周期删除策略:

通过设置定时任务,周期性的抽样key,判断是否过期,如果过期则删除。

周期删除有两种工作模式:

  • 在Redis的initServer()函数中,会按照server.hz的频率来执行过期key的清理,模式为SLOW,默认每秒10次。
  • Redis的每个事件循环前回调用beforeSleep()函数,执行过期key的清理,模式为FAST。
  • SLOW执行低频但清理更加彻底。FAST模型执行高频,但执行时机较短。

在这里插入图片描述

在这里插入图片描述

淘汰策略

内存淘汰策略执行的时机:
Redis会在处理客户端命令的方法processCommand()中尝试做内存淘汰。

Redis支持8种不同的策略进行key的淘汰,默认的淘汰策略是noeviction,不淘汰任何key,但是内存满的时候不允许写入新数据。

其他常见内存淘汰策略,通常分为对全体key处理和对设置了TTL的key处理。

包括按照TTL优先淘汰将要过期key。
对全体key,随机淘汰,对设置了TTL的key随机淘汰。

基于LRU算法对全体key或者设置了TTL的key进行淘汰。
基于LFU算法对全体key或者设置了TTL的key进行淘汰。

在这里插入图片描述

LRU与LFU

  • LRU(least recently used),最少最近使用。用当前时间减去最后一次访问时间,这个值越大,淘汰的优先级越高。
  • LRU是基于时间的,时间敏感,最近的,新出现的热点key,更有可能被常驻到内存中,而那些长时间没有使用的key则更有可能被淘汰掉。
  • LFU(least frequently used),最少频率使用。会统一每个key的访问频率,值越小,淘汰优先级越高。
  • LFU是频率敏感的,更适合保存包含有多个热点key,某个key上一次访问已经是昨天中午12:00,并且在昨天12:00的5分钟内,高频访问了200次,如果今天中午还有这样的需求,按照LFU的策略,昨天的热key会常驻在内存中。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VUE安装部署+应用

1.下载vscode 安装教程:https://blog.csdn.net/T1401026064/article/details/128692088 百度网盘:VSCodeUserSetup-x64-1.74.3.exe 提取码:8s8a 2.VUE教程 可以用!快捷输入代码框架。 教程:https://cn.vuejs.org/guid…

解决Git fatal: refusing to merge unrelated histories报错

问题描述 当在远程建立了一个仓库,并且远程的仓库已经初始化了的情况,使用 git remote add origin gitgithub.com:xxx/xxx.git命令添加远程仓库后,执行git pull,然后提示如下: 大致意思就是需要关联我们的本地和远程分支。按照…

【形心】不规则多边形形心计算方法(含面积计算)

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 不规则多边形形心计算若干方法小结 说明: 这里以凹多边形为例,方便排查所计算坐标不在多边形之外。 1. 正文 1.1 方法一 shap…

【网络编程】网络编程套接字(三)TCP网络程序

文章目录 简单的TCP网络程序一、服务器创建套接字二、服务器绑定套接字三、服务器监听四、服务器获取连接五、服务器处理请求六、对服务器进行简单测试七、客户端创建套接字八、客户端连接服务器九、客户端发起请求十、服务器客户端测试 多进程的TCP服务器一、忽略SIGCHLD信号二…

IDEA 搭建Android 开发环境

项目实战 废话不多说开始创建先第一个 Android 项目 步骤一 FILE → New → Project 步骤二-选择 Android 项目模板 选那个安卓机器人,如果没有这个选项,需要升级IDEA版本或者安装安卓插件 选择*Basic Activity* Next-下一步 步骤三-项目初始化 名称、包名、安装位置自行调整…

守护数智未来,开源网安受邀参加2023OWASP北京论坛

2023年7月14日,OWASP中国与网安加社区联合举办的“2023OWASP中国北京安全技术论坛”在北京圆满召开,开源网安受邀参加本次论坛并分享“软件供应链安全治理实践”。 本次“2023OWASP中国北京安全技术论坛”是OWASP中国北京地区年度重要活动之一&#xff…

解决ValueError: If using all scalar values, you must pass an index

使用字典创建DataFrame对象时,会报这样得错误 ValueError: If using all scalar values, you must pass an index 代码如下: 这是因为没有索引所致,所以,需要我们指定索引,来创建DataFrame对象。 模式为&#xff1a…

【C++】模板进阶—非类型模板参数、模板特化及模板的分离编译

🚀 作者简介:一名在后端领域学习,并渴望能够学有所成的追梦人。 🚁 个人主页:不 良 🔥 系列专栏:🛸C 🛹Linux 📕 学习格言:博观而约取&#xff0…

jar包发版至服务器Linux命令

maven -> clean compile install / package 使用WinSCP 或者其他软件在target下 找到jar包 传至服务器 找到原先jar包存放位置 cd /usr/local/xxx 通过线上端口号找到线程数 netstat -tunlp | grep 8080 杀死线程 kill -9 线程数 运行新jar包 nohup java -jar jar包名…

利用 jenkins 关联 Job 方式完善 RobotFramework 测试 Setup 以及 Teardown 后操作

目录 1.前言 2.Jekins 关联 Job 方式 1.前言 Jenkins是一个流行的持续集成和交付工具,它可以帮助自动化构建、测试和部署软件。与Robot Framework结合使用,可以实现更高效的测试工作流程。 在Robot Framework中,Setup和Teardown是测试用例…

文件IO_文件同步(附Linux-5.15.10内核源码分析)

目录 1.为什么要进行文件同步? 2.fsync函数介绍 2.1 fsync函数 2.2 fsync函数内核源码分析 2.3 fsync函数使用示例 3.fdatasync函数介绍 3.1 fdatasync函数 3.2 fdatasync函数内核源码分析 3.3 fdatasync函数使用示例 4.sync函数介绍 4.1 sync函数 4.2 …

第一阶段-第十一章 Python基础的综合案例(数据可视化-地图可视化)

目录 一、基础地图使用  1.学习目标  2.视觉映射器  3.本节的演示二、疫情地图-国内疫情地图  1.案例效果  2.函数的语法  3.本节的代码演示三、疫情地图-省级疫情地图  1.案例效果  2.本节的代码演示 说明:该文章是学习 黑马程序员在B站上分享的视…

SPRINGBOOT部署安装hello world

1.安装JAVA环境,设置为全局变量 用以下方法检查,安装是否正确 2.maven安装,并且修改setting中的镜像设置,改为国内阿里云镜像 3.idea中设置JDK版本号,IDEA中springboot不要选择3.0版本,会出现与jdk不匹…

如何在照片上添加水印?这三个方法让你轻松实现

我有个朋友他是一名摄影爱好者,他在旅行中经常能捕捉到一些绝美的照片。他为了分享这份美丽,决定将它们上传到社交媒体上。但是,他很担心别人未经许可就盗用了他的作品。于是他来想我请教这个问题。我就给他推荐了几款加水印软件,…

(学习笔记-TCP基础知识)TCP与UDP区别

UDP UDP不提供复杂的控制机制,利用IP提供面向[无连接]的通信服务。 UDP协议非常简单,头部只有8个字节(位),UDP的头部格式如下: 目标和源端口:主要是告诉UDP协议应该把报文发给哪个进程包长度:该字段保存了…

CentOS目录详解

在centos中,最顶层的目录称作根目录, 用/表示。/目录下用户可以再创建目录,但是有一些目录随着系统创建就已经存在,接下来重点介绍几个常用目录。 /bin(binary)包含了许多所有用户都可以访问的可执行文件&a…

轻松实现金蝶云星空与赛意SMOM系统的全面集成

1. 金蝶云星空:为运营协同与管控型企业提供通用ERP服务平台 金蝶云星空是基于当今先进管理理论和数十万家国内客户最佳应用实践开发的ERP服务平台。它针对事业部制、多地点、多工厂等企业和集团公司,提供了通用的企业资源计划(ERP&#xff0…

win键无效,键盘Win组合键突然不不能用如何解决?

电脑win键失效怎么办? 在使用windows系统的时候,发现一个问题,就是win键失效了,怎么按都没有反应,该怎么办呢? 键盘方面的原因 此时之是键盘的原因与系统本身没有关系,键盘屏蔽热键主要目标是…

【技能实训】DMS数据挖掘项目-Day13

文章目录 任务15【任务15.1】ClientFrame.java【任务15.2】ClientFrame.java【任务15.3】实现匹配日志信息或物流数据的数据保存功能(保存到本地文件),将15.2中,返回的匹配数据,保存到客户端文件中【任务15.4】实现物流…

恢复软件哪些好?推荐3款,亲试好用!

“想问下朋友们有什么好的恢复软件推荐吗?我的电脑数据经常都莫名其妙就找不到了,我也不敢随意进行操作。如果有好的数据恢复软件,快给我推荐推荐吧!” 电脑数据很多都是比较重要的,如果经常丢失数据,会对我…