redis原理(二)数据结构

 redis可以存储键与5种不同数据结构类型之间的映射:

String类型的底层实现只有一种数据结构,也就是动态字符串。而List、Hash、Set、ZSet都由两种底层数据结构实现。通常我们把这四种类型称为集合类型,它们的特点是一个键对应了一个集合的数据。下面分别介绍下

一、STRING字符串:

1、介绍:redis没有直接使用C语言传统的字符串表示,而是自己实现的叫做简单动态字符串SDS的抽象类型。C语言的字符串不记录自身的长度信息,而SDS则保存了长度信息,内部结构实现上类似于 Java 的ArrayList,这样将获取字符串长度的时间由O(N)降低到了O(1),同时可以避免缓冲区溢出和减少修改字符串长度时所需的内存重分配次数;

  • 对C语言中的字符串的封装和优化,c语言字符串不是二进制安全的,字符串中间不能有空格,空格标志结束
  • 频繁修改一个字符串时,会涉及到内存的重分配,比较消耗性能。(Redis中的简单动态字符串会有内存预分配和惰性空间释放)。
  • 如果字符串实际使用长度len<1M,实际分配空间=len长度来存储字符串+1字节存末尾空字符+len长度的预分配空闲内。
  • 如果字符串实际使用长度len>1M,实际分配空间=len长度来存储字符串+1字节存末尾空字符+1M长度的预分配空闲内存

2、底层数据结构:简单动态字符串(free、len、buf[])(可以保存文本+二进制+不会缓冲溢出+获取字符串长度时间[O1]);

3、大小:当字符串长度小于 1M 时,扩容都是加倍现有的空间,如果超过 1M,扩容时一次只会多扩 1M 的空间。需要注意的是字符串最大长度为 512M;

4、基本命令:set,get,strlen,exists,decr,incr,setex 等等;

set num 1;incr num【计数器】,expire key 60;ttl key 【设置过期时间+查看指定key的过期时间】;

5、应用场景:计数;

二、LIST列表:

1、底层数据结构:链表,链接上的每个节点都包含了一个字符串。

Redis中list是由两种数据结构构成的,数据少时用ziplist,数据多时用linkedlist(ziplist连锁更新耗时),当列表弹出了最后一个元素之后,该数据结构自动被删除,内存被回收。

扩展:也可将list模拟队列和栈的使用。

列表元素较少的情况下会使用一块连续的内存存储,这个结构是 ziplist,也即是压缩列表。它将所有的元素紧挨着一起存储,分配的是一块连续的内存。当数据量比较多的时候才会改成 quicklist。因为普通的链表需要的附加指针空间太大,会比较浪费空间,而且会加重内存的碎片化。

比如这个列表里存的只是 int 类型的数据,结构上还需要两个额外的指针 prev 和 next 。所以 Redis 将链表和 ziplist 结合起来组成了 quicklist。也就是将多个ziplist 使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。

linkedlist维护前后指针,占内存空间,还造成内存碎片化

ziplist没有前后指针,entry保存了上一个结点长度,所以也可以双向遍历,但是当一个结点长度变化了,后面结点都要变,连锁更新耗时

ziplist结构:

  • zlbytes:整个ziplist占字节数
  • zltail:尾结点相对于首地址偏移量
  • zllen:结点数
  • entry:保存了前一个结点长度+编码+内容
  • zlend:代表结束

2、基本命令:rpush、lpop、lpush、rpop,、lrange、llen 等。

3、应用场景:

(1)发布与订阅或者说消息队列: Redis 的列表结构常用来做异步队列使用。将需要延后处理的任务结构体序列化成字符串塞进 Redis 的列表,另一个线程从这个列表中轮询数据进行处理;

(2)慢查询。

三、SET集合:

1、底层数据结构:哈希表+整数数组。 Redis 的集合相当于 Java 语言里面的 HashSet,它内部的键值对是无序的唯一的。它的内部实现相当于一个特殊的字典,字典中所有的 value 都是一个值 NULL。由于是set,有天然去重功能。

2、常用命令:sadd、spop、smembers、sismember、scard、sinterstore、sunion 等。

3、使用场景:数据不重复+可以判断一个成员是否存在+交集并集(共同关注、粉丝,两个集合求交集)

四、HASH字典:

1、底层数据结构:Redis 的字典相当于 Java 语言里面的 HashMap,它是无序字典。内部实现结构上同Java 的 HashMap 也是一致的,同样的数组 + 链表二维结构。第一维 hash 的数组位置碰撞时,就会将碰撞的元素使用链表串接起来。

不同的是,Redis 的字典的值只能是字符串,另外它们 rehash 的方式不一样,因为Java 的 HashMap 在字典很大时,rehash 是个耗时的操作,需要一次性全部 rehash。Redis 为了高性能,不能堵塞服务,所以采用了渐进式 rehash 策略。

(1)触发rehash的时机:

字典类型容量变化过程叫做rehash,需要满足一定的条件才能触发扩容机制。服务器当前没有进行BGWRITEAOF或者BGSAVE命令,且当前键值对个数超过一维数组的大小,才会触发扩容。

如果当前键值对个数超过一维数组大小的五倍,无论是否在进行BGWRITEAOF或者BGSAVE命令,都会强制扩容。 Hash类型扩容后数组的长度为原来的二倍

缩容机制:如果当前键值对个数少于一维数组大小的十分之一,则触发缩容过程。缩容不会考虑当前服务器是否在进行BGWRITEAOF或者BGSAVE命令。

(2)Rehash过程

利用了两个哈希表进行的 , 有点类似数据库的迁移 , 读的时候先读旧库 , 读不到读新库 , 写的时候只写新库 ; 其他旧数据一点点的往新库上搬。

当触发扩容的时候,Redis会首先为ht[1] 分配一块内存空间。如果当前字典是一个比较大的字典,那么整个扩容过程的时间复杂度为O(n),直接完整进行扩容机制可能会导致Redis一段时间内停止服务。为了避免停止服务的情况,Redis的设计团队采用了渐进式rehash的策略,每次只对原哈希表中的一小部分进行搬迁,这样渐进式的进行,直到全部键值对都迁移到新的哈希表中。

首先,对于key的查询,我们需要到原来的哈希表中进行查找,如果找到对应的value,直接返回就可以了。如果没有找到,那么只有两种可能,一个是这个键值对已经搬迁到新的哈希表了,另外一种可能是根本就不存在这个键值对,无论是哪种可能,我们都需要再去新哈希表中对他进行查找,如果找到了就返回,如果找不到说明这个键值对不存在。

五、ZSET有序集合:

1、底层数据结构 :

ZSet数据结构类似于Set结构,只是ZSet结构中,每个元素都会有一个分值,然后所有元素按照分值的大小进行排列,相当于是一个进行了排序的链表。

如果ZSet是一个链表,而且内部元素是有序的,在进行元素插入和删除,以及查询的时候,就必须要遍历链表才行,时间复杂度就达到了O(n),这个在以单线程处理的Redis中是不能接受的。所以ZSet采用了一种跳跃表的实现。这个实现有点类似于Kafka存储消息是使用的稀疏索引。这种跳跃表的实现,其实和二分查找的思路有点接近,只是一方面因为二分查找只能适用于数组,而无法适用于链表,所以为了让链表有二分查找类似的效率,就以空间换时间来达到目的。

  • 操作时间复杂度O(logn)
  • 空间复杂度O(n)
  • 为何不用红黑树这些?:跳表实现简单,平衡树插入删除可能引发平衡调整,更加复杂,跳表只需要动动结点指针;做范围查找的时候,平衡树比skiplist操作要复杂。
  • 插入结点使用随机层数算法建立层数 每层晋升概率0.25

2、常用命令:zadd,zcard,zscore,zrange,zrevrange,zrem

3、应用场景: 跳跃表因为是一个根据分数权重进行排序的列表,可以再很多场景中进行应用,比如排行榜,搜索排序等等。

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

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

相关文章

【MATLAB】【数字信号处理】产生系统的单位冲激响应h(t)与H(z)零极点分布

一、实验目的与要求 产生h(t) 与H(z) 零极点分布 二、实验仪器 微机&#xff0c;仿真软件MATLAB 2022a 三、实验内容与测试结果 1.已知描述连续系统的微分方程为y(t)5y(t)6y(t)2x(t)8x(t) &#xff0c;计算系统的单位冲激响应h(t) 程序如下&#xff1a; clear all; ts0;…

JavaScript采集各大电商平台关于预制菜酸菜鱼销售量

因为我喜欢吃酸菜鱼&#xff0c;但是自己弄又弄不来&#xff0c;想从网上找找看看&#xff0c;但是种类多&#xff0c;自己逐个选择又太浪费时间。索性利用自己专业爬虫知识&#xff0c;一边检验我最近代码水平&#xff0c;另一方面还能选择到满意的年货。过去写个各大平台预制…

centos7 arm服务器编译安装gcc 8.2

前言 当前电脑的gcc版本为4.8.5&#xff0c;但是在编译其他依赖包的时候&#xff0c;出现各种奇怪的问题&#xff0c;会莫名其妙的中断编译。本地文章讲解如何自编译安装gcc&#xff0c;替换系统自带的gcc。 环境准备 gcc 需要 8.2&#xff1a;下载地址 开始编译 1、解压gcc…

医疗器械网络安全风险评定CVSS打分

为了完成医疗器械软件的网络安全风险评定相关文档&#xff0c;需要进行CVSS评分&#xff0c;这个评分对于第一次做的人来说感觉还是有些迷惑的&#xff0c;查了一些资料&#xff0c;留作参考。 CVSS 指的是 Common Vulnerability Scoring System&#xff0c;即通用漏洞评分系统…

QLExpress和Groovy对比

原理 Groovy groovy基于JVM运行。 编译时&#xff1a;将源文件编译成class文件后&#xff0c;用java的classLoader加载&#xff1b;运行时&#xff1a;直接用groovy classLoader加载 QLExpress QLExpress将文本解析成AST&#xff0c;用java对象表达后执行。 特点 Groo…

C++命名空间的using声明

在前边的C讲解中&#xff0c;使用输入输出流cin和cout前要加std::&#xff0c;每次前边都要加就会很麻烦。解决这个问题&#xff0c;我们就要了解一下命名空间和using声明。  命名空间会限定作用域具体格式及使用参照C入门讲解命名空间&#xff0c;上边的cin和cout就是声明在s…

大屏项目:react中实现3d效果的环形图包括指引线

参考链接3d环形图 3d效果的环形图 项目需求实现方式指引线&#xff08;线的样式字体颜色&#xff09; 项目需求 需要在大屏上实现一个3d的环形图&#xff0c;并且自带指引线&#xff0c;指引线的颜色和每段数据的颜色一样&#xff0c;文本内容变成白色&#xff0c;数字内容变…

最值得推荐的10个免费PDF转Word的方法

PDF转Word是一项很常见的操作&#xff0c;将PDF文件转换为Word文档可以方便我们对文件进行编辑和修改&#xff0c;而且Word格式也更加好打印。 最值得推荐的10个免费PDF转Word的方法 PDF 文件格式在很多场合都被广泛使用&#xff0c;但有时候我们需要修改 PDF 文件内容并保存&…

抖店入驻+运营全方位指导,开店篇!无货源/有货源统统适用

我是王路飞。 关于抖店的入驻和运营教程&#xff0c;准备出一个比较详细、系统的全方位指导内容&#xff0c;感兴趣的可以持续关注下。 不管你做的是无货源还是有货源模式&#xff0c;核心思路都是一样的&#xff0c;统统适用。 这篇文章&#xff0c;先给你们分享下抖店的入…

LLM之RAG实战(十五)| RAG的自动源引文验证技术

​ 在过去的一年里&#xff0c;检索增强生成&#xff08;RAG&#xff09;已经成为一种基于LLM的流行架构&#xff0c;旨在解决在基于知识的LLM最常见的挑战之一&#xff0c;可怕的幻觉。 一、RAG如何解决幻觉&#xff1f; RAG Pipeline包括两个关键组件&#xff1a;&…

Java零基础教学文档servlet(1)

【Web开发和HTTP协议】 1. Web开发概述 1.1 web概述 万维网&#xff08;英语&#xff1a;World Wide Web&#xff09;亦作WWW、Web、全球广域网&#xff0c;是一个透过互联网访问的&#xff0c;由许多互相链接的超文本组成的信息系统。英国科学家蒂姆伯纳斯-李于1989年发明了…

类脑研究之脑组成及神经系统相关理论!大脑是什么?大脑和脑有什么区别?大脑皮层和脑膜什么关系?人的神经系统有哪些?

目录 1 引言2 神经系统3 脑组成3.1 大脑成分3.2 大脑外部&#xff1a;脑膜3.3 大脑中部&#xff1a;大脑皮层3.4 大脑内部3.5 脑干3.6 小脑 1 引言 为了深入研究类脑&#xff0c;必须了解大脑的结构和机制。从神经系统分级和脑组成两个角度出发&#xff0c;详细介绍了大脑的生…

1.如何记录每个变量携带的数据:DataFrame与Series

序列格式和列表区别&#xff1a;序列格式可以直接汇总&#xff1a;均值&#xff0c;总和&#xff0c;百分位数等 DataFrame Series

[链路层] 点对点协议 PPP

目录 1、PPP协议的特点 2、PPP协议的组成和帧格式 3、PPP协议的工作状态 目前使用得最广泛的数据链路层协议是点对点协议PPP(Point-to-Point Protocol)。 1、PPP协议的特点 我们知道&#xff0c;互联网用户通常都要连接到某个 ISP 才能接入到互联网。PPP 协议就是用户计算机…

Codeforces Round 918 (Div. 4)补题

Odd One Out&#xff08;Problem - A - Codeforces&#xff09; 题目大意&#xff1a;有三个数&#xff0c;其中两个相同&#xff0c;找出不同的那个数。 #include<bits/stdc.h> using namespace std; int main() {int t;scanf("%d",&t);while(t--){vect…

【面试合集】说说提高微信小程序的应用速度的手段有哪些?

面试官&#xff1a;说说提高微信小程序的应用速度的手段有哪些&#xff1f; 一、是什么 小程序启动会常常遇到如下图场景&#xff1a; 这是因为&#xff0c;小程序首次启动前&#xff0c;微信会在小程序启动前为小程序准备好通用的运行环境&#xff0c;如运行中的线程和一些基…

Endothelin-1(内皮素-1) ELISA kit

灵敏、快速的内皮素-1 ELISA试剂盒&#xff0c;适用于心血管和应激相关研究 内皮素&#xff08;Endothelin, ET&#xff09;是由血管内皮细胞产生的异肽&#xff0c;具有强大的血管收缩活性。这种肽由三个独立的基因编码&#xff0c;经过加工产生39个残基的 大ET 分子&#xff…

服务器 conda update 失败解决方法

1. 强制 conda update 租借一台服务器&#xff0c;发现 conda 版本是4.10.3&#xff0c;需要升级&#xff0c;使用了如下命令都没有效果&#xff0c;仍然是一样的版本 conda update conda update --all conda update -n base -c defaults conda最后强制用conda-forge通道更新…

D25XB60-ASEMI电机整流桥D25XB60

编辑&#xff1a;ll D25XB60-ASEMI电机整流桥D25XB60 型号&#xff1a;D25XB60 品牌&#xff1a;ASEMI 封装&#xff1a;GBJ-5&#xff08;带康铜丝&#xff09; 特性&#xff1a;插件、整流桥 平均正向整流电流&#xff08;Id&#xff09;&#xff1a;25A 最大反向击穿…

Jenkins实现自作自定义镜像并推送Harbor并编写目标服务器准备脚本

Jerkin 制作自定义镜像推送到Harbor docker build -t mytest:$tag . docker login -u admin -p Harbor12345 178.119.30.133:80 docker tag mytest:$tag 178.119.30.133:80/repo/mytest:$tag docker push 178.119.30.133:80/repo/mytest:$tag编写部署脚本 部署项目需要通过Pub…