当前位置: 首页 > article >正文

【Redis】深入解析 Redis 五大数据结构

文章目录

  • 一、字符串(String)​
    • 特点​
    • 使用场景​
    • 底层实现​
  • 二、列表(List)​
    • 特点​
    • 使用场景​
    • 底层实现​
  • 三、集合(Set)​
    • 特点​
    • 使用场景​
    • 底层实现​
  • 四、哈希(Hash)​
    • 特点​
    • 使用场景​
    • 底层实现​
  • 五、有序集合(Sorted Set)​
    • 特点​
    • 使用场景​
    • 底层实现​

Redis 作为一款高性能的内存数据库,被广泛应用于各种场景。其丰富的数据结构是它强大功能的基石,今天我们就来深入探讨 Redis 的五大数据结构,包括它们的使用场景和底层实现。​

一、字符串(String)​

特点​

字符串是 Redis 最基本的数据结构。它可以存储任何形式的字符串,包括二进制数据,最大能存储 512MB 的数据。​

使用场景​

缓存数据:这是字符串最常见的使用场景。比如将数据库查询结果缓存起来,下次查询时直接从 Redis 获取,减少数据库压力。例如,一个新闻网站可以将热门新闻的内容缓存为字符串,当大量用户请求时,直接从 Redis 读取,而无需频繁查询数据库。​
计数器:利用 Redis 的原子自增(INCR)和自减(DECR)操作,字符串可以很方便地实现计数器功能。比如统计文章的阅读量、用户的点赞数等。每有一次阅读或点赞操作,就对相应的字符串键执行 INCR 命令。​
分布式锁:在分布式系统中,多个节点可能同时访问共享资源。可以通过在 Redis 中设置一个特定的字符串值作为锁标志,利用 SETNX(SET if Not eXists)命令来实现分布式锁。当一个节点成功设置了这个字符串值,就表示它获得了锁,其他节点只能等待。​

底层实现​

Redis 的字符串在底层是由 SDS(Simple Dynamic String)简单动态字符串来实现的。SDS 的结构包含了长度、容量和字符数组等信息。相比于传统的 C 字符串,SDS 具有以下优势:​
获取长度时间复杂度为 O (1):C 字符串获取长度需要遍历整个字符串,时间复杂度为 O (n),而 SDS 直接通过结构中的长度字段获取,时间复杂度为 O (1)。​
避免缓冲区溢出:SDS 在进行字符串操作时,会先检查空间是否足够,如果不足会自动扩展空间,避免了缓冲区溢出问题。​
减少内存重新分配次数:SDS 采用了预分配和惰性释放策略,减少了内存重新分配的次数,提高了性能。​

二、列表(List)​

特点​

列表是一个有序的字符串链表,每个节点都包含一个字符串值。可以在列表的两端进行插入和删除操作,时间复杂度为 O (1)。​

使用场景​

消息队列:列表的 LPUSH(从列表头部插入元素)和 RPOP(从列表尾部弹出元素)操作可以很方便地实现一个简单的消息队列。生产者将消息通过 LPUSH 命令插入到列表头部,消费者通过 RPOP 命令从列表尾部获取消息,从而实现消息的异步处理。​
最新消息排行:利用列表的有序性,可以将最新发布的消息依次插入到列表头部。通过 LRANGE 命令可以获取指定范围内的最新消息,比如获取最新的 10 条新闻。​
用户操作记录:记录用户的操作历史,比如用户的浏览记录、订单记录等。每次用户进行操作时,将操作记录通过 LPUSH 插入到列表头部,这样可以方便地查看用户的最新操作记录。​

底层实现​

Redis 列表的底层实现是由双向链表和压缩列表实现的。当列表元素较少且每个元素长度较短时,使用压缩列表来节省内存空间。压缩列表是一种经过特殊编码的连续内存块,它将多个元素紧凑地存储在一起,减少了内存碎片。当列表元素较多或者元素长度较长时,会转换为双向链表。双向链表可以方便地在两端进行插入和删除操作,时间复杂度为 O (1)。​

三、集合(Set)​

特点​

集合是一个无序的字符串集合,其中每个元素都是唯一的,不允许重复。集合支持交集、并集、差集等操作。​

使用场景​

标签系统:在一个社交平台中,用户可以为自己发布的内容添加多个标签。通过将用户的标签存储在集合中,可以方便地进行标签相关的操作,比如获取拥有某个标签的所有用户,或者获取两个用户共同拥有的标签(交集操作)。​
去重:当需要对大量数据进行去重时,集合是一个很好的选择。例如,在统计网站的独立访客时,将每个访客的 IP 地址存储在集合中,由于集合元素的唯一性,自动就实现了去重功能。​
抽奖系统:可以将参与抽奖的用户 ID 存储在集合中,然后通过随机从集合中取出元素的方式来实现抽奖功能。​

底层实现​

Redis 集合的底层实现是由哈希表和整数集合实现的。当集合中的元素都是整数且元素个数较少时,使用整数集合。整数集合是一种紧凑的数组结构,它按照从小到大的顺序存储元素,并且支持高效的插入、删除和查找操作。当集合中的元素包含非整数或者元素个数较多时,会转换为哈希表。哈希表使用链地址法解决冲突,通过哈希函数将元素映射到不同的桶中,从而实现快速的查找和插入操作。​

四、哈希(Hash)​

特点​

哈希是一个键值对集合,其中每个键值对中的键都是唯一的。哈希特别适合存储对象,比如用户信息、商品信息等。​

使用场景​

存储对象:将对象的属性和值以键值对的形式存储在哈希中。例如,存储用户信息,包括用户名、年龄、性别、邮箱等。可以将用户 ID 作为哈希的键,用户的各项属性作为哈希的子键,对应的值作为子键的值。这样在获取和修改用户信息时,可以只操作相关的属性,而不需要操作整个对象。​
购物车:在电商系统中,购物车可以用哈希来实现。将用户 ID 作为哈希的键,商品 ID 作为子键,商品数量作为子键的值。这样可以方便地对购物车中的商品进行添加、删除和修改数量等操作。​

底层实现​

Redis 哈希的底层实现是由压缩列表和哈希表实现的。当哈希中的键值对数量较少且每个键值对的长度较短时,使用压缩列表。压缩列表将多个键值对紧凑地存储在一起,节省内存空间。当哈希中的键值对数量较多或者键值对长度较长时,会转换为哈希表。哈希表通过哈希函数将键映射到不同的桶中,每个桶中存储一个键值对,通过链地址法解决冲突。​

五、有序集合(Sorted Set)​

特点​

有序集合是一个有序的字符串集合,每个元素都关联一个分数(score),集合根据分数从小到大排序。元素是唯一的,但分数可以重复。​

使用场景​

排行榜:这是有序集合最典型的使用场景。比如游戏中的玩家排行榜,根据玩家的积分作为分数,将玩家 ID 作为元素存储在有序集合中。通过 ZRANGE 命令可以很方便地获取排行榜上的玩家信息,比如获取排名前 10 的玩家。​
时间序列数据:在监控系统中,需要记录不同时间点的监控数据。可以将时间戳作为分数,监控数据作为元素存储在有序集合中。这样可以方便地根据时间范围查询监控数据。​

底层实现​

Redis 有序集合的底层实现是由跳跃表(Skip List)和哈希表实现的。跳跃表是一种随机化的数据结构,它通过在每个节点中维护多个指向其他节点的指针,实现了快速的查找和插入操作。哈希表用于存储元素到分数的映射,以保证元素的唯一性。跳跃表和哈希表的结合,既保证了有序性,又保证了查找和插入的高效性。​

Redis 的五大数据结构各有特点,适用于不同的场景。了解它们的底层实现原理,有助于我们在实际应用中更加合理地使用 Redis,发挥它的最大性能优势。在后续的文章中,我们还会深入探讨 Redis 的其他高级特性,敬请关注。​


http://www.kler.cn/a/600619.html

相关文章:

  • 【构建性能分析插件设计与实现:打造前端项目的性能透视镜】
  • Ubuntu Server版本Ubuntu 24.04.2 LTS下载与安装-详细教程,细致到每一步都有说明
  • 如何在jupyter notebook中使用django框架
  • 隔空打印,IPP,IPD,HP Jetdirect协议的区别(Mac添加打印机四种协议的区别)
  • 科学计算(2):矩阵特征值计算
  • 【Linux系统篇】:进程流水线的精密齿轮--创建,替换,终止与等待的工业级管控艺术
  • 【机器学习】线性回归和逻辑回归的区别在哪?
  • 什么是 LLM(大语言模型)?——从直觉到应用的全面解读
  • PHP eval 长度限制绕过与 Webshell 获取
  • 【linux】ubuntu 用户管理
  • javaSE.多维数组
  • 开发中后端返回下划线数据,要不要统一转驼峰?
  • CUDA 学习(3)——CUDA 初步实践
  • 基于Flask的通用登录注册模块,并代理跳转到目标网址
  • ANYmal Parkour: Learning Agile Navigation for Quadrupedal Robots
  • 投sci论文自己查重方法
  • wordpress主题开发框架(灵狐框架),开发文档使用教程
  • 在K8S中使用ArgoCD做持续部署
  • 云原生CI/CD | Argo CD 详细介绍 (一)
  • 在本地Windows机器加载大模型并生成内容