Redis中的数据结构与内部编码

news2024/11/17 3:08:24

 

  本篇文章主要是对 Redis 常见的数据结构进行讲解,同时还对其所对应的不同的内部编码进行讲解。希望本篇文章会对你有所帮助。

文章目录

一、五大数据结构

二、数据结构对应的编码方式

String

hash

list

set

zset


🙋‍♂️ 作者:@Ggggggtm 🙋‍♂️

👀 专栏:Redis 👀

💥 标题:Redis中的数据结构与内部编码 💥

 ❣️ 寄语:与其忙着诉苦,不如低头赶路,奋路前行,终将遇到一番好风景 ❣️

  我们知道,redis是支持不同的数据类型的,而不同的数据类型底层所采用的数据结构也有所差异,同时不同的数据结构也会有不同的操作指令。我们这里所说的不同的数据类型都是指的value的类型,而key的类型固定是string的。上篇文章讲解到的type指令,其返回值是key所对应的value的数据类型!

一、五大数据结构

   Redis的键值对中,value所用到的五种主要的数据结构,它们分别是:

  1. String(字符串):最基本的类型,可以包含任何形式的数据,比如一个文本、JSON字符串或者二进制数据。

  2. List(列表):一个有序的字符串列表,元素的顺序由插入顺序决定,可以在两端进行插入和删除操作。

  3. Set(集合):一个不重复且无序的字符串集合,可对集合中的元素进行添加、删除和判断某个元素是否存在的操作。

  4. Hash(哈希表):类似于关联数组,包含字段和与其对应的值,常用于存储对象。

  5. Zset(有序集合):类似于集合,但每个元素都关联一个分数,可以按照分数进行排序,适合构建排行榜等功能。

  具体可看下图:

  

  Redis 底层在实现上述数据结构的时候,会在源码层面针对上述实现进行特定的优化,来达到节省时间或者节省空间的效果。简单来说,数据结构的内部具体实现不是固定统一的,会根据不同的情况,redis会自动适配合适的数据结构。但是每个数据结构的底层实现有固定的几种方式。

  举个例子,redis承诺现在我这有个hash表,你进行查询、插入、删除操作都保证O(1)的书简复杂度。但是这个背后的实现,不一定就是一个标准的hash表。可能再特定场景下,使用别的数据结构实现。但是仍然保证时间复杂度符合承诺。

  那么哦我们现在就会有两个大致方向上的理解:

  • 数据结构是指redis 承诺给你的。也可以理解成数据类型;
  • 编码方式是redis内部底层的实现;
  • 一个数据结构有对应固定的编码方式。

二、数据结构对应的编码方式

  实际上每种数据结构都有自己底层的内部编码实现,而且是多种实现这样 Redis 会在合适的场景选择合适的内部编码。具体数据结构所对应的编码方式如下:

数据结构内部编码
string1.raw
2.embstr
3.int
hash1.hashtable
2.ziplist
list1.linkedlist
2.ziplist
set1.hashtable
2.intset
zset1.skiplist
2.ziplist

  下面我们来详细解释一下不同的内部编码。

String

  Redis中 String 的内部编码有三种:int、raw、embstr。

  1. int编码

    • 当字符串可以被解释为整数时,Redis会将该字符串以int编码进行存储,节省内存空间。
    • int编码使用64位有符号整数来表示,其范围为-2^63到2^63-1。
    • 当字符串的值处于int编码的范围内时,Redis会使用int编码来存储,这样可以减少内存占用并提高性能。
  2. raw编码

    • 当字符串无法被解释为整数时,Redis会以raw编码进行存储。
    • raw编码使用简单动态字符串(SDS)来表示,SDS是一种带有缓冲区的字符串表示形式,可以动态扩展和收缩,适用于存储任意长度的字符串数据。
    • raw编码适用于存储包含非整数数据的字符串,如文本、JSON、XML等。
  3. embstr编码

    • embstr是一种特殊的内部编码方式,用于存储长度较短的字符串。
    • 当字符串长度在一定范围内(默认为39字节)时,Redis会使用embstr编码来存储,以进一步减少内存开销。
    • embstr编码实际上将字符串值和其他元数据一起存储在一个连续的内存块中,节省了额外指针和分配内存的开销。

  SDS动态字符串可参考文章:Redis(设计与实现):01---数据结构之SDS动态字符串(raw、embstr、int、struct sdshdr)_sds类型的int与raw查询速度的区别

hash

  Redis 中的 Hash 类型可以使用两种内部编码方式:hashtable 和 ziplist。

  1. Hashtable:

    • Hashtable 是 Redis 中 Hash 类型的默认内部编码方式。
    • 当 Hash 中包含的键值对数量较多,或者键值对的值较大时,Redis 会自动将 Hash 内部编码为 Hashtable。
    • Hashtable 使用哈希表来存储键值对,可以快速进行数据查找,适合处理大规模的数据。
  2. Ziplist:

    • Ziplist 是一种紧凑的数据结构,适合存储小规模的数据。
    • 当 Hash 中包含的键值对数量较少,且每个键值对的键和值的长度都较小时,Redis 会选择使用 Ziplist 进行内部编码。
    • Ziplist 使用一段连续的内存空间来存储键值对,节约了内存的使用,但查找效率没有哈希表高。
    • 由于元素过少,通过遍历,时间复杂度还是可以认为是 O(1)

  总结来说,当 Hash 数据较大或者键值对较复杂时,Redis 会使用 Hashtable 进行内部编码以获得更好的性能;而当 Hash 数据较小且简单时,Redis 会选择使用 Ziplist 进行内部编码以节约内存空间。

  具体底层实现细节可参考文章:Redis(设计与实现):06---数据结构之压缩列表(ziplist、struct ziplist)_4位长,介于0至12之间的无符号整数Redis(设计与实现):03---数据结构之字典(hashtable、struct dictht、struct dictEntry、struct dict)-CSDN博客

list

  在 Redis 中,List 类型可以使用三种不同的内部编码方式:linkedlist、ziplist 和 quicklist。

  1. Linkedlist(双向链表):

    • linkedlist 内部编码主要适用于 List 包含的元素数量较多,或者元素的大小较大的情况。它通过指针将元素连接在一起,支持快速的插入和删除操作,适合处理大规模的数据。
  2. Ziplist(压缩列表):

    • ziplist 内部编码适用于 List 包含的元素数量较少,且每个元素的大小都比较小时。Ziplist 使用紧凑的数据结构来存储元素,节约了内存的使用,但查找和修改操作的效率没有 linkedlist 高。
  3. Quicklist(快速列表):

    • quicklist 是 Redis 为了优化 List 类型而引入的一种内部编码方式。它实际上是将多个 ziplist 连接在一起形成的一个双向链表结构。quicklist 既具备了 ziplist 节约内存空间的优点,又能够快速地处理大规模的数据,同时还兼顾了快速的插入和删除操作。

  综上所述,Redis 根据 List 中元素的数量和大小来选择合适的内部编码方式:linkedlist 适用于大规模数据的场景,ziplist 适用于节约内存的场景,而 quicklist 则是为了兼顾以上两种场景而设计的一种高效内部编码方式。大部分场景下都是使用的quicklist。

set

  在 Redis 中,Set 类型可以使用两种不同的内部编码方式:hashtable 和 intset。

  1. Hashtable(哈希表):

    • 当 Set 中的元素数量较多,或者元素较长时,Redis 会选择使用 hashtable 内部编码。这种编码方式使用了哈希表结构来存储元素,它提供了较快的查找、插入和删除操作,适用于处理较大规模的数据。
  2. Intset(整数集合):

    • 当 Set 中的所有元素都是整数,并且数量较少时,Redis 会选择使用 intset 内部编码。intset 使用紧凑的数组结构来存储整数元素,节省了内存空间的使用,并且提供了高效的操作,适用于存储小规模的整数数据集。

  在实际使用中,Redis 根据 Set 的特点(元素数量、元素类型等)来动态地选择合适的内部编码方式,以提高性能和节约内存空间。通过使用合适的内部编码方式,Redis 能够更好地满足不同场景下对 Set 数据类型的需求。

  intset底层实现可参考文章:Redis(设计与实现):04---数据结构之整数集合(intset、struct intset)

zset

  在 Redis 中,有序集合(Sorted Set)类型可以使用两种不同的内部编码方式:skiplist 和 ziplist。

  1. Skiplist(跳跃表):

    • 当有序集合中的成员数量较多或者成员较长时,Redis 会选择使用 skiplist 内部编码。跳跃表是一种基于链表的数据结构,它可以提供快速的插入、删除和查找操作。
    • Skiplist 编码方式适用于处理较大规模的有序集合数据,因为它能够保持较高的性能并且具有良好的平衡性能。
  2. Ziplist(压缩列表):

    • 当有序集合中的成员数量较少且每个成员都比较短小精悍时,Redis 会选择使用 ziplist 内部编码。压缩列表是一种紧凑的数据结构,可以节省内存空间,适用于存储较小规模的有序集合数据。
    • Ziplist 内部编码方式对于小型的有序集合数据具有较好的存储效率和操作性能。

  根据有序集合的实际情况,Redis 会动态地选择合适的内部编码方式,以便在不同场景下提供最佳的性能和内存利用率。

  skiplist底层实现原理可参考文章:Redis(设计与实现):05---数据结构之跳跃表(skiplist、struct zskiplistNode、struct zskiplist)_skiplist和zskiplistnode

  可以看到每种数据结构都有至少两种以上的内部编码实现,例如list数据结构包含了linkedlist和ziplist 两种内部编码。同时有些内部编码,例如ziplist,可以作为多种数据结构的内部实现,可以通过object encoding命令查询内部编码:

   Redis这样设计有两个好处:

  • 可以改进内部编码,而对外的数据结构和命令没有任何影响,这样一旦开发出更优秀的内部编码,无需改动外部数据结构和命令,例如Redis 3.2提供了quicklist,结合了ziplist和linkedlist两者的优势,为列表类型提供了一种更为优秀的内部编码实现,而对用户来说基本无感知。
  • 多种内部编码实现可以在不同场景下发挥各自的优势,例如ziplist 比较节省内存,但是在列表元素比较多的情况下,性能会下降,这时候Redis 会根据配置选项将列表类型的内部实现转换为linkedlist,整个过程用户同样无感知。

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

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

相关文章

node.js(express)+MongoDB快速搭建后端---新手教程

前言: Node.js是一个基于 Chrome V8引擎的JavaScript运行环境,是对于前端工程师来说学习成本最小的后端实现方法,本篇文章总结如何从0-1写一个后端的登录接口 一、检查node环境 先检查自己的node是否安装 一般来说前端工程师的电脑环境肯定…

长安链使用Golang编写智能合约教程(二)

本篇说的是长安链2.3.的版本的智能合约,虽然不知道两者有什么区别,但是编译器区分。 教程三会写一些,其他比较常用SDK方法的解释和使用方法 编写前的注意事项: 1、运行一条带有Doker_GoVM的链 2、建议直接用官方的在线IDE去写合…

【机器学习】Pandas中to_pickle()函数的介绍与机器学习中的应用

【机器学习】Pandas中to_pickle()函数的介绍和机器学习中的应用 🌈 欢迎莅临我的个人主页👈这里是我深耕Python编程、机器学习和自然语言处理(NLP)领域,并乐于分享知识与经验的小天地!🎇 &#…

【Android】【netd】网络相关调试技巧

网络调试技巧总结 ifconfig ifconfig 查看网卡信息 ifconfig -S tcpdump tcpdump -i any -n icmp 查看流量出入ip addr 上面的log 以及ifcong -S 信息可以知道,当前是从wlan0 网卡请求数据。 iptable iptable 部分指令 //禁止www.baidu.com 网址流量进入&a…

网易面试:手撕定时器

概述: 本文使用STL容器-set以及Linux提供的timerfd来实现定时器组件 所谓定时器就是管理大量定时任务,使其能按照超时时间有序地被执行 需求分析: 1.数据结构的选择:存储定时任务 2.驱动方式:如何选择一个任务并执…

在HTML和CSS当中运用显示隐藏

1.显示与隐藏 盒子显示:display:block;盒子隐藏: display:none:隐藏该元素并且该元素所占的空间也不存在了。 visibility:hidden:隐藏该元素但是该元素所占的内存空间还存在,即“隐身效果”。 2.圆角边框 在CSS2中添加圆角,我们不得不使用背景图像&am…

redis面试知识点

Redis知识点 Redis的RDB和AOF机制各是什么?它们有什么区别? 答:Redis提供了RDB和AOF两种数据持久化机制,适用于不同的场景。 RDB是通过在特定的时刻对内存中的完整的数据复制快照进行持久化的。 RDB工作原理: 当执行…

Python 机器学习 基础 之 无监督学习 【聚类(clustering)/k均值聚类/凝聚聚类/DBSCAN】的简单说明

Python 机器学习 基础 之 无监督学习 【聚类(clustering)/k均值聚类/凝聚聚类/DBSCAN】的简单说明 目录 Python 机器学习 基础 之 无监督学习 【聚类(clustering)/k均值聚类/凝聚聚类/DBSCAN】的简单说明 一、简单介绍 二、聚类…

Vue3兼容低版本浏览器(ie11,chrome63)

1、插件安装 为了使你的项目兼容 Chrome 63,你需要确保包含适当的 polyfills 和插件配置。你已经在使用 legacy 插件,但在代码中可能缺少一些配置或插件顺序有问题。以下是几个可能的改进: 安装 vitejs/plugin-legacy 插件: 确保…

Midjourney保姆级教程(五):Midjourney图生图

Midjourney生成图片的方式除了使用文字描述生成图片外,还有“图生图”的方式,可以让生成的图片更接近参考的图片。 今天我们来聊聊“图生图”的方式。 一、模仿获取propmt 很多时候,我们不知道画什么内容的图片,大家可以关注内…

一款拥有15000+POC漏洞扫描工具

1 工具介绍 0x01 免责声明 请勿使用本文中所提供的任何技术信息或代码工具进行非法测试和违法行为。若使用者利用本文中技术信息或代码工具对任何计算机系统造成的任何直接或者间接的后果及损失,均由使用者本人负责。本文所提供的技术信息或代码工具仅供于学习&am…

vue3快速上手笔记(尚硅谷)

[TOC]# 1. Vue3简介 2020年9月18日,Vue.js发布版3.0版本,代号:One Piece(n 经历了:4800次提交、40个RFC、600次PR、300贡献者 官方发版地址:Release v3.0.0 One Piece vuejs/core 截止2023年10月&#…

经典必读:智能制造数字化工厂建设方案

导语 大家好,我是社长,老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》 完整版文件和更多学习资料,请球友到知识星球【智能仓储物流技术研习社】自行下载 战略背景:响应《中国制造2025》及"…

Kibana使用教程

Kibana使您能够轻松地向Elasticsearch发送请求,并以交互方式分析、可视化和管理数据。 1.安装 1.1 docker安装Kibana 如果你还没安装Elasticsearch,先执行docker安装Elasticsearch,下面是单机部署。 创建一个ES网络: docker n…

idea视图中顶部菜单栏找不到VCS

问题描述 idea视图中顶部菜单栏找不到VCS: 解决方案: 直接选择配置过git,此处操作: File->Settings->Version Control-> 点击 ->选择项目->VCS选择none ->点击apply -> 点击ok:

怎样修改库包的文件名?

python中,安装crypto模块时,会遇到crypto文件夹都是小写字母的情况,引用时又是首字母大写,这个时候,需要把库包文件名首字母改为大写字母。windows中一般的文件名命名中字母的大小写是不进行区分的,但是在p…

期权具体怎么交易详细的操作流程?

期权就是股票,唯一区别标的物上证指数,会看大盘吧,交易两个方向认购做多,认沽做空,双向t0交易,期权具体交易流程可以理解选择方向多和空,选开仓的合约,买入开仓和平仓没了&#xff0…

win10如何查看本机ip地址?三招搞定,快来试试吧

在数字化时代,IP地址作为网络设备的唯一标识,对于计算机使用者来说具有重要意义。无论是为了进行网络设置、远程连接,还是解决网络问题,了解如何查看本机IP地址都是一项必备技能。对于使用Windows 10操作系统的用户来说&#xff0…

Idea工具的使用技巧与常见问题解决方案

一、使用技巧 1、启动微服务配置 如上图,在编辑配置选项,将对应的启动入口类加进去, 增加jvm启动参数, 比如: -Denvuat 或者 -Denvuat -Dfile.encodingUTF-8 启动配置可能不是-Denvuat,这个自己看代…

媒体邀约资源报道(重庆邀约媒体)

传媒如春雨,润物细无声,大家好,我是51媒体网胡老师。 重庆拥有电视台、广播电台、报纸、杂志以及网络媒体等多种丰富的媒体资源,企业和机构可以根据自身需求和活动特点选择合适的媒体进行邀约合作。以下是重庆地区的一些主要媒体…