深入理解Redis

news2025/2/7 18:38:57

1.数据结构类型

数据结构-SDS-简单动态字符串

Redis构建了一种新字符串结构,称为简单动态字符串(Simple Dynamic String),简称SDS。 Redis未直接使用C语言的字符串,如:char* s = "hello",本质是字符数组: {'h', 'e', 'l', 'l', 'o', '\0'}。因为C语言字符串存在很多问题:a. 获取字符串长度的需要通过运算;  b. 非二进制安全; c. 不可修改;

而使用SDS存在以下优点: a. 获取字符串长度的时间复杂度为O(1);  b. 支持动态扩容;  c. 减少内存分配次数;  d. 二进制安全;

数据结构-IntSet-整数集合

IntSet是Redis中set集合的一种实现方式,基于整数数组来实现,并且具备长度可变、有序等特征。

具备如下特点:   a. Redis会确保Intset中的元素唯一、有序   b. 具备类型升级机制,可以节省内存空间;  c. 底层采用二分查找方式来查询;

HT-哈希表/字典-结构

Dict由三部分组成,分别是:哈希表(DictHashTable)、哈希节点(DictEntry)、字典(Dict),  类似java的HashTable,底层是数组加链表来解决哈希冲突。

ict中的HashTable就是数组结合单向链表的实现,当集合中元素较多时,必然导致哈希冲突增多,链表过长,则查询效率会大大降低。

Dict在每次操作键值对时都会检查负载因子(LoadFactor = used/size) , 满足以下两种情况时会触发哈希表扩容:

  •     哈希表的 LoadFactor >= 1,并且服务器没有执行 BGSAVE 或者 BGREWRITEAOF 等后台进程;   
  •  哈希表的 LoadFactor > 5 ;
  •    扩容大小为第一个大于等于used + 1的2^n;(比如used的是8,则扩容为8+1=9的最近的2的n次方16)

Dict每次删除元素时,也会对负载因子做检查,满足以下情况时会触发哈希表缩容:

  •     当LoadFactor < 0.1 时,会做哈希表收缩:  
  •    收缩大小为第一个大于等于used 的2^n(比如used的是7,则缩容为7的最近的2的n次方8, 但是如果used为8呢?刚好8那岂不是又要扩容?还是说不会出现)

Dict的rehash:

    不管是扩容还是收缩,必定会创建新的哈希表,导致哈希表的size和sizemask变化,而key的查询与sizemask有关。       

 因此必须对哈希表中的每一个key重新计算索引,插入新的哈希表,这个过程称为rehash。

Dict的渐进式rehash:     Dict的rehash并不是一次性完成的。试想一下,如果Dict中包含数百万的entry,要在一次rehash完成,极有可能导致主线程阻塞。         因此Dict的rehash是分多次、渐进式的完成,因此称为渐进式rehash。   

  渐进式rehash过程是这样的:       

 a. 计算新hash表的realeSize,值取决于当前要做的是扩容还是收缩:      

       如果是扩容,则新size为第一个大于等于dict.ht[0].used + 1的2^n           

      如果是收缩,则新size为第一个大于等于dict.ht[0].used的2^n (不得小于4)      

b. 按照新的realeSize申请内存空间,创建dictht,并赋值给dict.ht[1];       

 c. 设置dict.rehashidx = 0,标示开始rehash;         

d. 每次执行新增、查询、修改、删除操作时,都检查一下dict.rehashidx是否大于-1,如果是则将dict.ht[0].table[rehashidx]的entry链 表rehash到dict.ht[1],并且将rehashidx++(注意下一步没有展示)。直至dict.ht[0]的所有数据都rehash到dict.ht[1];  

 e. 将dict.ht[1]赋值给dict.ht[0],给dict.ht[1]初始化为空哈希表,释放原来的dict.ht[0]的内存;

 f. 将rehashidx赋值为-1,代表rehash结束;

   注意:在rehash过程中,新增操作则直接写入ht[1],查询、修改和删除则会在dict.ht[0]和dict.ht[1]依次查找并执行。这样可确保ht[0]的数据只减不增,随rehash最终为空;

渐进式哈希过程

ZipList

ZipList 是一种特殊的“双端链表” ,由一系列特殊编码的连续内存块组成。可以在任意一端进行压入/弹出操作, 并且该操作的时间复杂度为 O(1)。

特征:

a. 列表节点之间不是通过指针连接,而是记录上一节点和本节点长度来寻址,内存占用较低;

 b. 如果列表数据过多,导致链表过长,可能影响查询性能;  

 c. 增或删较大数据时有可能发生连锁更新问题 连锁更新:假设我们有N个连续长度为250~253字节之间的entry,因此entry的previous_entry_length属性用1个字节。如果新增一个entry长度超过253,则后续previous_entry_length需变为5个字节来存储,ZipList这种特殊情况下产生的连续多次空间扩展操作称之为连锁更新(Cascade Update)。新增、删除都可能导致连锁更新的发生。

QuickList

QuickList的特点:是一个节点为ZipList的双端链表;

特点:

a. 节点采用ZipList,解决了传统链表的内存占用问题;

b. 控制了ZipList大小,解决连续内存空间申请效率问题;

c. 中间节点可以压缩,进一步节省了内存;

SkipList

SkipList(跳表)首先是链表,但与传统链表相比有几点差异:

a. 元素按照升序排列存储;

b.  节点可能包含多个指针,指针跨度不同;

特点:

a. 跳跃表是一个双向链表,每个节点都包含score和ele值;    

b. 节点按照score值排序,score值一样则按照ele字典排序;    

c. 每个节点都可以包含多层指针,层数是1到32之间的随机数;        

d. 不同层指针到下一个节点的跨度不同,层级越高,跨度越大;  

e. 增删改查效率与红黑树基本一致,实现却更简单;

2.redis数据结构

String-数据结构

List-数据结构

Redis的List结构类似一个双端链表,是简单的字符串列表,按照插入顺序排序;可以从首、尾操作列表中的元素,添加一个元素到列表的头部(左边)或者尾部(右边);

一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素);

a. 在3.2版本之前,Redis采用ZipList和LinkedList来实现List,当元素数量小于512并且元素大小小于64字节时采用ZipList编码,超过则采用LinkedList编码;

b. 在3.2版本之后,Redis统一采用QuickList来实现List:

Set-数据结构

Set是Redis中的无序集合,满足下列特点:

a. 不保证有序性;  b. 保证元素唯一;  

c. 查询效率极高; 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。添加,删除,查找的复杂度都是 O(1)。

Set是Redis中的无序集合,满足下列特点:

a. 不保证有序性;

 b. 保证元素唯一;  

c. 查询效率极高;

集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。添加,删除,查找的复杂度

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

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

相关文章

数字后端培训项目Floorplan常见问题系列专题续集1

今天继续给大家分享下数字IC后端设计实现floorplan阶段常见问题系列专题。这些问题都是来自于咱们社区IC后端训练营学员提问的问题库。目前这部分问题库已经积累了4年了&#xff0c;后面会陆续分享这方面的问题。 希望对大家的数字后端学习和工作有所帮助。 数字后端项目Floor…

【TaskBasics】- KRTS C++示例精讲(3)

TaskBasics示例讲解 目录 TaskBasics示例讲解结构说明 项目打开请查看【BaseFunction精讲】。 结构说明 TaskBasics&#xff1a;应用层程序&#xff0c;主要用于人机交互、数据显示、内核层数据交互等&#xff1b; TaskBasics.h &#xff1a; 数据定义TaskBasics.cpp&#xff…

jenkins集成工具(一)部署php项目

目录 什么是CI 、CD Jenkins集成工具 一、Jenkins介绍 二、jenkins的安装和部署 环境部署 安装jenkins 安装gitlab 配置镜像源进行安装 修改密码 安装git工具 上传测试代码 Jenkins部署php项目wordpress 发布php代码 安装插件 测试代码发布 实现发布成功发送邮件…

在交叉编译中,常见的ELF(elf)到底是什么意思?

ELF 是 Executable and Linkable Format 的缩写&#xff0c;中文翻译为“可执行与可链接格式”。它是一种通用的文件格式&#xff0c;主要用于存储可执行文件、目标文件&#xff08;编译后的中间文件&#xff09;、动态库&#xff08;.so 文件&#xff09;以及内存转储文件&…

图神经网络_图嵌入_Struc2Vec

0 背景 之前的node embedding方式&#xff0c;都是基于近邻关系&#xff0c;但是有些节点没有近邻&#xff0c;也有结构相似性。如图中的u、v节点。 struc2vec算法适用于捕获结构相似性。 1 相似度&#xff08;距离&#xff09;计算 1.1 公式 f k ( u , v ) f k − 1 ( u …

Linux内核中Typec CC检测原理及主从模式切换原理

一&#xff0c;Typec CC引脚定义 可以看到&#xff0c;数据传输主要有TX/RX两组差分信号&#xff0c;CC1和CC2是两个关键引脚&#xff0c;作用很多&#xff1a; • 探测连接&#xff0c;区分正反面&#xff0c;区分DFP和UFP&#xff0c;也就是主从 • 配置Vbus&#xff0c;有US…

uniapp通过v-if进行判断时,会出现闪屏?【已解决】

1.问题&#xff1a;按钮切换时&#xff0c;通过v-if来判断&#xff0c;会出现闪烁情况&#xff0c;影响用户体验 2.v-if 闪烁问题可能的原因 ‌条件切换频繁‌&#xff1a;如果 v-if 指令的条件在短时间内频繁切换&#xff0c;会导致元素不断被销毁和重新创建&#xff0c;从而…

webrtc获取IceCandidate流程

在WebRTC(Web Real-Time Communication)中,ICECandidate是一个关键概念,它用于描述在建立点对点(P2P)连接时可以考虑的潜在通信端点。以下是关于WebRTC中ICECandidate的详细解释: 一、ICECandidate的定义 ICECandidate对象通常包含以下关键属性: foundation:用于唯一…

计算机网络习题(第1章 概论 第2章 数据通信基础)

第1章 概论 1、计算机网络 2、互联网 3、计算机网络体系结构 分层模型 OSI/RM 7层模型 TCP/IP 5层模型 协议、PDU、SDU、SAP等术语 数据封装&#xff08;计算&#xff09; 第2章 数据通信基础 1、数据通信系统组成 2、主要性能指标 数据传输速率 码元速率 时延 3…

Springboot项目下面使用Vue3 + ElementPlus搭建侧边栏首页

Springboot项目下面、在html 页面 Vue3 ElementPlus 搭建侧边栏首页 1、效果图 2、static 文件下面的项目结构 3、代码实现 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>首页</title><…

【C++11】可变参数模版

目录 一、可变参数模版 1.1 基本语法及原理 1.2 包拓展 1.3 empalce系列接口 一、可变参数模版 之前我们在C语言中就学过可变参数&#xff0c;但是模版类型是固定的&#xff0c;怎么变呢&#xff1f;这里c11就给出了可变参数模版 1.1 基本语法及原理 C11支持可变参数模…

FFmpeg在python里推流被处理过的视频流

链式算法处理视频流 视频源是本地摄像头 # codinggbk # 本地摄像头直接推流到 RTMP 服务器 import cv2 import mediapipe as mp import subprocess as sp# 初始化 Mediapipe mp_drawing mp.solutions.drawing_utils mp_drawing_styles mp.solutions.drawing_styles mp_holis…

我的秋招总结

我的秋招总结 个人背景 双非本&#xff0c;985硕&#xff0c;科班 准备情况 以求职为目的学习Java的时间大概一年。 八股&#xff0c;一开始主要是看B站黑马的八股文课程&#xff0c;背JavaGuide和小林coding还有面试鸭。 算法&#xff0c;250&#xff0c;刷了3遍左右 项目&…

C++:单例模式

创建自己的对象&#xff0c;同时确保对象的唯一性。 单例类只能有一个实例☞静态成员static☞静态成员 必须类外初始化 单例类必须自己创建自己的唯一实例 单例类必须给所有其他对象提供这一实例 静态成员类内部可以访问 构造函数私有化☞构造函数私有外部不能创建&#x…

RBTree(红黑树)

目录 红黑树的概念 红黑树的性质 红黑树节点的定义 红黑树的插入 1. 按照二叉搜索的树规则插入新节点 2. 检测新节点插入后&#xff0c;红黑树的性质是否造到破坏 红黑树的检测 红黑树的删除 红黑树和AVL树的比较 红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&…

linux自动化一键批量检查主机端口

1、准备 我们可以使用下面命令关闭一个端口 sudo iptables -A INPUT -p tcp --dport 端口号 -j DROP我关闭的是22端口&#xff0c;各位可以关其它的或者打开其它端口测试&#xff0c;谨慎关闭22端口&#xff01;不然就会像我下面一样握手超时&#x1f62d;&#x1f62d;&…

Python大数据可视化:基于python大数据的电脑硬件推荐系统_flask+Hadoop+spider

开发语言&#xff1a;Python框架&#xff1a;flaskPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录 管理员功能界面 价格区间界面 用户信息界面 品牌管理 笔记本管理 电脑主机…

AEO海关认证的注意事项

AEO海关认证的注意事项繁多且至关重要&#xff0c;企业需细致准备&#xff0c;确保万无一失。 首先&#xff0c;企业需深入研读相关政策文件&#xff0c;如《中华人民共和国海关注册登记和备案企业信用管理办法》及《海关高级认证企业标准》&#xff0c;以政策为指引&#xff0…

MySQL如何只取根据某列连续重复行的第一条记录

前言 MySQL如何只取根据某列连续重复行的第一条记录&#xff0c;条件&#xff1a;某列、连续、验重 建表准备 DROP TABLE IF EXISTS test; CREATE TABLE test (id bigint NOT NULL,time datetime NULL DEFAULT NULL,price int NULL DEFAULT NULL,PRIMARY KEY (id) USING BT…

c++编译过程初识

编译过程 预处理&#xff1a;主要是执行一些预处理指令&#xff0c;主要是#开头的代码&#xff0c;如#include 的头文件、#define 定义的宏常量、#ifdef #ifndef #endif等条件编译的代码&#xff0c;具体包括查找头文件、进行宏替换、根据条件编译等操作。 g -E example.cpp -…