Redis数据库(二):Redis 常用的五种数据结构

Redis 能够做到高性能的原因主要有两个,一是它本身是内存型数据库,二是采用了多种适用于不同场景的底层数据结构。
Redis 常用的数据结构支持字符串、列表、哈希表、集合和有序集合。实现这些数据结构的底层数据结构有 6 种,分别是简单动态字符串、双向列表、压缩列表、哈希表、跳表和整数数组。
在这里插入图片描述

List、 Hash、Set 和 Sorted Set 这四种数据类型,都有两种底层实现结构。通常情况下,我们会 把这四种类型称为集合类型,它们的特点是一个键对应了一个集合的数据。
那么,有一些问题值得我们去思考:

  • 既然 Redis 是键值型数据结构,那么键和值本身之间用什么结构组织?
  • 操作集合数据的效率和哪些因素有关?

2.1 键和值用什么数据结构组织?

为了实现从键到值的快速访问,Redis 使用了一个哈希表来保存所有键值对。一个哈希表,其实就是一个数组,数组的每个元素称为一个哈希桶。
因为值本身的类型可以是列表、哈希表等集合类型,因此哈希桶存放的并不是值本身,而是 *key*value 的入口地址。
在这里插入图片描述

使用哈希表的好处就是能够在 O(1) 时间内根据 key 查找到相应的 value。但,哈希表的性能并非一直是 O(1)。当需要解决哈希表冲突和再哈希(rehash)时可能会带来性能的下降。

2.1.1 哈希表冲突

哈希表冲突是指根据不同的 key 计算得到了相同的哈希值,就是说有不同的键值对放到了同一个哈希桶当中。因为哈希桶的个数是有限的,因此总会遇到哈希冲突。
解决哈希冲突的方法有多种,Redis 采用的是链式哈希。具体来说,就是同一个哈希桶中的多个元素用一个链表来保存,它们之间通过指针来连接。
在这里插入图片描述

链式哈希会带一个问题是,当位于同一个桶中的元素太多时,查询桶中元素的时间复杂度会退化到 O(n),这是我们不愿看到的。解决办法就是对旧的哈希表进行 rehash,将新的哈希值存放在一个更大的哈希桶中。但如果直接进行原地哈希,必然会导致性能急剧下降,解决的办法就是将 rehash 的操作均摊到之后的操作中。

2.1.2 渐进式 rehash

渐进式 rehash 的思想是在拷贝数据时,Redis 仍然正常处理客户端请求,每处理一个请求 时,从哈希表 1 中的第一个索引位置开始,顺带着将这个索引位置上的所有 entries 拷贝 到哈希表 2 中;等处理下一个请求时,再顺带拷贝哈希表 1 中的下一个索引位置的 entries。
在这里插入图片描述

这样就巧妙地把一次性大量拷贝的开销,分摊到了多次处理请求的过程中,避免了耗时操作,保证了数据的快速访问。

2.2 操作数据集合的效率

查找一个集合类型的值的过程是:先通过全局哈希表找到对应的哈希桶位置,然后在集合进行增删改查。那么,集合的操作效率与哪些因素有关呢?
首先是与集合底层采用的数据结构有关,例如哈希表的查询时间复杂度要优于链表的。其次是与这些操作本身的执行特点有关,例如读取一个元素和读取一个范围的元素。

2.2.1 底层数据结构的特点

Redis 实现集合类型的底层数据结构有双向列表、整数数组、哈希表、压缩列表和跳表。
哈希表的特点刚才已经介绍过了。双向列表和整数数组比较常见,这里就不再详细展开了。
重点介绍一个压缩列表和跳表。

压缩列表

压缩列表类似于一个数组,数组中的每一个元素都对应保存一个数据。和数组不同的是,压缩列表在表头有三个字段 zlbytes、zltail 和 zllen,分别表示列表长度、列表尾的 偏移量和列表中的 entry 个数;压缩列表在表尾还有一个 zlend,表示列表结束。
在这里插入图片描述

在压缩列表中,如果我们要查找定位第一个元素和最后一个元素,可以通过表头三个字段的长度直接定位,复杂度是 O(1)。而查找其他元素时,就没有这么高效了,只能逐个查找,此时的复杂度就是 O(N) 了。

跳表

跳表在链表的基础上,增加了多级索引,通过索引位置的几个跳转,实现数据的快速定位,跳表的查询过程如下图所示:
在这里插入图片描述

以上五种数据结构的时间复杂度如下表所示:
在这里插入图片描述

2.2.2 不同操作的复杂度

集合类型的操作方法很多,例如获取单个元素、多个元素、判断某个元素是否在集合当中。而不同数据结构的同一种操作方法的时间复杂度不同,因此有必要了解不同操作方法的时间复杂度。

  1. 单元素操作时间复杂度为 O(1);
  2. 范围操作比较耗时。当返回一个范围内的元素时,例如返回集合、List 某个范围的元素,时间复杂度为 O(N)。
  3. 统计元素个数比较高效。压缩列表、双向列表、整数数组这些数据结构中专门记录了元素的个数,统计执行效率较高。
  4. 特殊位置的元素操作效率与数据结构密切相关。例如对于 List 而言,在头尾进行操作元素的时间复杂度为 O(1),而在中间位置操作元素的时间复杂度为 O(N)。

2.3 使用数据结构的建议

选择 Redis 的数据结构时,需要综合考虑数据的特点、操作需求、内存占用和性能要求等多个因素。
选择 Redis 数据结构时,应该考虑以下几个因素:

  1. 数据访问模式
    字符串(String):适用于简单的 key-value 存储,比如缓存用户会话、计数器、或是简单的数据存取。
    哈希(Hash):适合存储对象、结构化数据,如用户信息、商品详情等。哈希允许在单一 key 下保存多个字段(字段值对),非常适合于存储较小的对象。
    列表(List):适合存储有序的集合,比如消息队列、任务队列、用户操作日志等。支持推入、弹出操作,符合生产者-消费者模型。
    集合(Set):适合存储无序且唯一的元素集合,用于去重操作、标签分类等。例如,存储用户订阅的标签列表,或是某些“推荐系统”的推荐项。
    有序集合(Sorted Set):适合存储带有权重的有序数据,支持根据分数进行排序。适用于排行榜、优先级队列、延迟队列等应用场景。

  2. 性能要求
    存储效率:不同数据结构的存储方式和空间效率不同。比如,集合(Set)适合去重,哈希(Hash)适合存储对象,如果需要存储大量字段和小值数据,使用哈希结构可以节省内存。
    操作效率:不同数据结构在操作时的复杂度也不同。一般来说,字符串操作最简单,复杂度为 O(1),而有序集合(Sorted Set)的某些操作,如添加、删除元素的复杂度可能为 O(log N)。

  3. 数据大小与访问频率
    • 如果需要频繁对数据进行增、删、改、查等操作,选择操作复杂度较低的数据结构,例如字符串和哈希。
    • 对于大数据量和高并发的场景,考虑 Redis 的内存消耗和性能瓶颈。比如,HyperLogLog 在大数据量去重时非常高效。

  4. 使用场景
    缓存:大多数缓存场景使用字符串(String)或哈希(Hash)。例如,缓存一整个页面或用户信息。
    队列:使用列表(List)或有序集合(Sorted Set)来实现消息队列、任务调度等。
    去重与标签:集合(Set)适用于去重和标签管理。
    排行榜与优先级队列:使用有序集合(Sorted Set)存储带权重的数据,并根据分数进行排序。

  5. 数据过期与持久化
    • Redis 提供了 EXPIRE 命令来为 key 设置过期时间,但不同数据结构的持久化策略可能不同。根据业务需求决定是否需要启用 Redis 的持久化机制(RDB 或 AOF),以及数据结构的持久化需求。

总结来说,选择 Redis 数据结构的关键是结合具体的业务需求、访问模式、性能要求等因素来进行权衡。在有些情况下,可能还需要多种数据结构的组合使用,以达到最佳效果。

实际上,在 Redis 7.4 版本中,已经支持 9 种数据结构,分别是String、Hash、List、Set、Sorted set、Stream、Bitmap、Bitfield以及Geospatial。后四种数据结构会专门再写一篇文章进行介绍。

觉得有用可以点个赞。

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

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

相关文章

C++STL(六)——list模拟

目录 本次所需实现的三个类一、结点类的模拟实现构造函数 二、迭代器类的模拟实现为什么有迭代器类迭代器类的模板参数说明构造函数运算符的重载- -运算符的重载和!运算符的重载*运算符的重载->运算符的重载引入模板第二个和第三个参数 三、list的模拟实现3.1 默认成员函数构…

国产编辑器EverEdit - 替换功能详解

1 替换 1.1 应用场景 替换文本是在文档编辑过程中不可回避的操作,是将指定的关键词替换为新的文本,比如:写代码时修改变量名等。 1.2 使用方法 1.2.1 基本替换 使用主菜单查找 -> 替换,或使用快捷键Ctrl H,会打…

LIMO:上海交大的工作 “少即是多” LLM 推理

25年2月来自上海交大、SII 和 GAIR 的论文“LIMO: Less is More for Reasoning”。 一个挑战是在大语言模型(LLM)中的复杂推理。虽然传统观点认为复杂的推理任务需要大量的训练数据(通常超过 100,000 个示例),但本文展…

防御保护作业二

拓扑图 需求 需求一: 需求二: 需求三: 需求四: 需求五: 需求六: 需求七: 需求分析 1.按照要求进行设备IP地址的配置 2.在FW上开启DHCP功能,并配置不同的全局地址池,为…

蓝桥与力扣刷题(226 翻转二叉树)

题目:给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 示例 1: 输入:root [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1]示例 2: 输入:root [2,1,3] 输出:[2,…

大型语言模型(LLM)中的自适应推理预算管理:基于约束策略优化的解决方案

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

[EAI-033] SFT 记忆,RL 泛化,LLM和VLM的消融研究

Paper Card 论文标题:SFT Memorizes, RL Generalizes: A Comparative Study of Foundation Model Post-training 论文作者:Tianzhe Chu, Yuexiang Zhai, Jihan Yang, Shengbang Tong, Saining Xie, Dale Schuurmans, Quoc V. Le, Sergey Levine, Yi Ma 论…

大数据-259 离线数仓 - Griffin架构 修改配置 pom.xml sparkProperties 编译启动

点一下关注吧!!!非常感谢!!持续更新!!! Java篇开始了! 目前开始更新 MyBatis,一起深入浅出! 目前已经更新到了: Hadoop&#xff0…

【时时三省】(C语言基础)基础习题1

山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 1.什么是程序?什么是程序设计 程序是为实现特定目标或解决特定问题,用计算机能理解和执行的语言编写的一系列指令的集合。 程序设计是问题分析,设计算法…

防火墙用户认证实验

1、创建vlan10和vlan20 2、将接口划分到对应的vlan中 [FW]interface GigabitEthernet 1/0/1.1 [FW-GigabitEthernet1/0/1.1]ip address 172.16.1.254 24 [FW-GigabitEthernet1/0/1.1]vlan-type dot1q 10 [FW]interface GigabitEthernet 1/0/1.2 [FW-GigabitEthernet1/0/1.1]ip …

VUE项目中实现权限控制,菜单权限,按钮权限,接口权限,路由权限,操作权限,数据权限实现

VUE项目中实现权限控制,菜单权限,按钮权限,接口权限,路由权限,操作权限,数据权限实现 权限系统分类(RBAC)引言菜单权限按钮权限接口权限路由权限 菜单权限方案方案一:菜单…

ESXi Host Client创建ubuntu虚拟机教程及NVIDIA显卡驱动安装

参考文章 VMware虚拟机显卡直通记录 AIGC 实战(环境篇) - EXSI 8.0 Debian安装RTX3060显卡驱动 重点介绍 client版本是7.0.3 注意:下图中不要选择BIOS 按照两个链接中的方法进行操作,以及本章节的上面几个图片的配置之后&a…

DeepSeek帮助做【真】软件需求-而不是批量刷废话

尝试给DeepSeek一份系统用例规约,让它帮判断哪些地方还没有覆盖涉众利益。结果见以下 需求工作的重点可以放在建模精细的真实现状流程和精细的真实涉众利益上,AI帮助推演系统需求。

apache-poi导出excel数据

excel导出 自动设置宽度&#xff0c;设置标题框&#xff0c;设置数据边框。 excel导出 添加依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.2</version></dependency>…

10 FastAPI 的自动文档

FastAPI 是一个功能强大且易于使用的 Web 框架&#xff0c;它的最大亮点之一就是内置的 自动文档生成 功能。通过集成 Swagger UI 和 ReDoc&#xff0c;FastAPI 可以自动为我们的 API 生成交互式文档。这不仅使得开发者能够更快速地了解和测试 API&#xff0c;还能够为前端开发…

微软AI研究团队推出LLaVA-Rad:轻量级开源基础模型,助力先进临床放射学报告生成

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

mysql8.0使用MHA实现高可用

一、MHA 介绍 MHA&#xff08;Master HA&#xff09;是一款开源的 MySQL 的高可用程序&#xff0c;它为 MySQL 主从复制架构提供了 automating master failover 功能。MHA 在监控到 master 节点故障时&#xff0c;会提升其中拥有最新数据的 slave 节点成为新的master 节点&…

D3实现站点路线图demo分享

分享通过D3实现的站点路线分布图demo&#xff0c;后续会继续更新其他功能。 功能点 点位弹窗 效果图如下&#xff1a; 轨迹高亮 效果图如下&#xff1a; 添加路线箭头 箭头展示逻辑&#xff1a;根据高速路线最后两个点位&#xff0c;计算得出箭头的点位 效果图如下&#x…

【系统架构设计师】操作系统 ③ ( 存储管理 | 页式存储弊端 - 段式存储引入 | 段式存储 | 段表 | 段表结构 | 逻辑地址 的 合法段地址判断 )

文章目录 一、页式存储弊端 - 段式存储引入1、页式存储弊端 - 内存碎片2、页式存储弊端 - 逻辑结构不匹配3、段式存储引入 二、段式存储 简介1、段式存储2、段表3、段表 结构4、段内地址 / 段内偏移5、段式存储 优缺点6、段式存储 与 页式存储 对比 三、逻辑地址 的 合法段地址…

物联网软件开发与应用方向应该怎样学习,学习哪些内容,就业方向是怎样?(文末领取整套学习视频,课件)物联网硬件开发与嵌入式系统

随着物联网技术的飞速发展&#xff0c;物联网软件开发与应用方向成为了众多开发者关注的焦点。那么&#xff0c;如何在这个领域中脱颖而出呢&#xff1f;本文将为你提供一份详细的学习指南&#xff0c;帮助你从零开始&#xff0c;逐步掌握物联网软件开发与应用的核心技能。 一…