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

【Redis】5种基础数据结构介绍及应用

考察频率难度
60%⭐⭐

这个方向的问题也是非常基础的,所以一般不会直接被当做一个单独的问题。常见的形式是结合你简历上的项目或者场景题来提问,即实际应用场景、是否可以优化、如何选择等。

由于场景题和实际项目差异较大,所以本文就只做基础的讲解,如果笔者后面想到遇见过的场景题,也会做博客来讲解。

由于 Redis 数据结构的特殊性,每一个基础的数据结构其实都对应一个或者多个更底层是数据结构。由于对应关系比较复杂,出于篇幅以及复杂度考虑,更底层的讲解,笔者想要单独来写。

基础数据结构简介

在数据的江湖里,Redis无疑是那位神秘莫测、武功高强的武林盟主。今天,我们要介绍的就是Redis的五个顶级弟子(Redis 到现在已经有 9 种数据结构了),他们各怀绝技,行走江湖无往不利。话不多说,让我们一睹这五兄弟的风采!

Redis 有五种基本数据类型,这五种数据类型分别是:string(字符串)、hash(哈希)、list(列表)、set(集合)、sorted set(有序集合,也叫 zset)。

结构类型结构存储的值结构的读写能力
String可以是字符串、整数或浮点数对整个字符串或者字符串的一部分进行操作;对整数或浮点数进行自增或自减操作;
List一个链表,链表上的每个节点都包含一个字符串对链表的两端进行 push 和 pop 操作,读取单个或多个元素;根据值查找或删除元素;
Set包含字符串的无序集合字符串的集合,包含基础的方法有看是否存在添加、获取、删除;还包含计算交集、并集、差集等;
Hash包含键值对的无序散列表包含方法有添加、获取、删除单个元素;
Zset和散列一样,用于存储键值对字符串成员与浮点数分数之间的有序映射;元素的排列顺序由分数的大小决定;包含方法有添加、获取、删除单个元素以及根据分值范围或成员来获取元素;

基础数据结构详解

内容其实比较简单,我觉得理解的重点在于这个结构怎么用,能够用来做什么?所以我在梳理时,围绕图例命令执行场景来阐述。

String字符串

String 是 Redis 中最基本的数据类型,一个 key 对应一个 value。

String 是最基本的 key-value 结构,key 是唯一标识,value 是具体的值,value其实不仅是字符串,也可以是数字(整数或浮点数),value 最多可以容纳的数据长度是 512M

常见指令

命令介绍
SET key value设置指定 key 的值
SETNX key value只有在 key 不存在时设置 key 的值
GET key获取指定 key 的值
MSET key1 value1 key2 value2 ...设置一个或多个指定 key 的值
MGET key1 key2 ...获取一个或多个指定 key 的值
STRLEN key返回 key 所储存的字符串值的长度
INCR key将 key 中储存的数字值(整型和浮点型)增一
DECR key将 key 中储存的数字值(整型和浮点型)减一
INCRBY/DECRBY key increment将 key 中储存的数字值(整型和浮点型)加/减 increment
EXISTS key判断指定 key 是否存在
DEL key(通用)删除指定的 key
EXPIRE key seconds(通用)给指定 key 设置过期时间
APPEND key value给指定 key 后面追加值 value

应用场景

  • 缓存数据:字符串是缓存数据的最常用数据结构,比如缓存用户信息、产品详情等。

  • 计数器:使用INCR、DECR等命令,可以轻松实现各种计数功能,如网站访问量、点赞数等。

  • 会话存储:将用户会话信息存储在字符串中,便于快速读取和更新。

  • 共享 Session 信息

List列表

Redis中的List其实就是链表(Redis用双端链表实现List)。

List 列表是简单的字符串列表,按照插入顺序排序,可以从头部或尾部向 List 列表添加元素。

使用List结构,我们可以轻松地实现最新消息排队功能(比如新浪微博的TimeLine)。List的另一个应用就是消息队列,可以利用List的 PUSH 操作,将任务存放在List中,然后工作线程再用 POP 操作将任务取出进行执行。

常见指令

命令介绍
LPUSH key value1 value2 ..在指定列表的头部(左边)添加一个或多个元素
RPUSH key value1 value2 ...在指定列表的尾部(右边)添加一个或多个元素
LSET key index value将指定列表索引 index 位置的值设置为 value
LPOP key移除并获取指定列表的第一个元素(最左边)
RPOP key移除并获取指定列表的最后一个元素(最右边)
LLEN key获取列表元素数量
LRANGE key start end获取列表 start 和 end 之间 的元素

应用场景

  • 任务队列:列表可以用作任务队列,支持从两端插入和删除元素。

  • 消息队列:可以用列表来实现简单的消息队列,保证消息的顺序性。

  • 日志存储:将日志条目存储在列表中,便于按时间顺序追加和读取。

Set集合

Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。

Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

Set 类型时无需且唯一的键值组合,它的存储顺序不会按照插入的先后顺序进行存储,即是无序的

一个集合最多可以存储 2^31 - 1 个元素。概念和数学中的集合基本类似,可以交集、并集、差集等等,所以 Set 类型除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集。

Set 类型和 List 类型的区别如下:

  • List 可以存储重复元素,Set 只能存储非重复元素。
  • List 是按照元素的先后顺序存储元素的,而 Set 则是无序方式存储元素的。

常见指令

命令介绍
SADD key member1 member2 ...向指定集合添加一个或多个元素
SMEMBERS key获取指定集合中的所有元素
SCARD key获取指定集合的元素数量
SISMEMBER key member判断指定元素是否在指定集合中
SINTER key1 key2 ...获取给定所有集合的交集
SINTERSTORE destination key1 key2 ...将给定所有集合的交集存储在 destination 中
SUNION key1 key2 ...获取给定所有集合的并集
SUNIONSTORE destination key1 key2 ...将给定所有集合的并集存储在 destination 中
SDIFF key1 key2 ...获取给定所有集合的差集
SDIFFSTORE destination key1 key2 ...将给定所有集合的差集存储在 destination 中
SPOP key count随机移除并获取指定集合中一个或多个元素
SRANDMEMBER key count

随机获取指定集合中指定数量的元素

应用场景

集合的主要几个特性:无序、不可重复、支持并交差集等。借助这几个特性,常见的使用场景为:

  • 去重:集合天生不允许重复元素,非常适合用于去重场景。

  • 标签管理:适合存储用户标签、商品标签等。

  • 社交网络:可以用来管理好友关系、共同兴趣等。

但是这里有一个需要注意的风险。Set 的并集、交集和差集的计算复杂度较高,在数据量较大的情况下,如果直接执行这些计算,会导致 Redis 示例阻塞。

在主从集群中,为了避免主库因为 Set 做聚合计算(并集、交集和差集)时导致主库被阻止,我们可以选择一个从库完成聚合统计,或者把数据返回给客户端,由客户端来完成聚合统计。

Hash散列

Hash 是一个 String 类型的 field(字段) 和 value(值) 的映射表,Hash 特别适合用于存储对象。

Hash 与 String 对象的区别如下图所示:

常见指令

命令介绍
HSET key field value设置指定哈希表中指定字段的值
HSETNX key field value只有指定字段不存在时设置指定字段的值
HMSET key field1 value1 field2 value2 ...同时将一个或多个 field-value (域-值)对设置到指定哈希表中
HGET key field获取指定哈希表中指定字段的值
HMGET key field1 field2 ...获取指定哈希表中一个或者多个指定字段的值
HGETALL key获取指定哈希表中所有的键值对
HEXISTS key field查看指定哈希表中指定的字段是否存在
HDEL key field1 field2 ...删除一个或多个哈希表字段
HLEN key获取指定哈希表中字段的数量

应用场景

  • 存储对象:哈希非常适合存储具有多个字段的对象,如用户信息、商品信息等。

  • 轻量级的数据存储:可以存储相对较小的数据,如配置项、状态信息等。

  • 减少内存消耗:对于多字段数据,使用哈希可以比字符串节省内存。

Zset有序集合

Zset 和 Set 一样也是 String 类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个 double 类型的分数。Redis 正是通过分数来为集合中的成员进行从小到大的排序。

有序集合的成员是唯一的, 但分数(score)却可以重复。有序集合是通过两种数据结构实现:

  1. 压缩列表(ziplist): ziplist是为了提高存储效率而设计的一种特殊编码的双向链表。它可以存储字符串或者整数,存储整数时是采用整数的二进制而不是字符串形式存储。它能在O(1)的时间复杂度下完成list两端的push和pop操作。但是因为每次操作都需要重新分配ziplist的内存,所以实际复杂度和ziplist的内存使用量相关
  2. 跳跃表(zSkiplist): 跳跃表的性能可以保证在查找,删除,添加等操作的时候在对数期望时间内完成,这个性能是可以和平衡树来相比较的,而且在实现方面比平衡树要优雅,这是采用跳跃表的主要原因。跳跃表的复杂度是O(log(n))。

常见指令

命令介绍
ZADD key score1 member1 score2 member2 ...向指定有序集合添加一个或多个元素
ZCARD KEY获取指定有序集合的元素数量
ZSCORE key member获取指定有序集合中指定元素的 score 值
ZINTERSTORE destination numkeys key1 key2 ...将给定所有有序集合的交集存储在 destination 中,对相同元素对应的 score 值进行 SUM 聚合操作,numkeys 为集合数量
ZUNIONSTORE destination numkeys key1 key2 ...求并集,其它和 ZINTERSTORE 类似
ZDIFF destination numkeys key1 key2 ...求差集,其它和 ZINTERSTORE 类似
ZRANGE key start end获取指定有序集合 start 和 end 之间的元素(score 从低到高)
ZREVRANGE key start end获取指定有序集合 start 和 end 之间的元素(score 从高到底)
ZREVRANK key member获取指定有序集合中指定元素的排名(score 从大到小排序)

应用场景

Zset 类型(Sorted Set,有序集合) 可以根据元素的权重来排序,我们可以自己来决定每个元素的权重值。在面对需要展示最新列表、排行榜等场景时,如果数据更新频繁或者需要分页显示,可以优先考虑使用 Zset。

  • 排行榜:有序集合非常适合实现排行榜,按分数排序展示前N名用户。

  • 带权重的数据存储:适用于需要按权重排序的数据,如评分系统。

  • 延迟队列:可以根据分数(时间戳)实现延迟任务队列。

总结

Redis数据结构五兄弟,各个身怀绝技,各有千秋。无论是字符串的快剑手、哈希的万花筒、列表的快马、集合的独行侠,还是有序集合的智者,他们都在数据江湖中扮演着不可或缺的角色。希望这篇介绍能让你对Redis的五种基础数据结构有一个更生动形象的了解。让我们一起在Redis的世界中,成为数据江湖的侠客吧!

哈哈,抽象的标题、抽象的开头和抽象的结尾,笔者实在是懒得去想这些东西要怎么写了,但是又想搞一篇有趣的文章,于是去请教了万能的人工智能 ChatGPt,还可以吧,描述很传神。

本文修改自笔者之前在自己博客网站上发布过的一篇博客,那篇博客是一个史诗长度的博客,详细介绍了每一种基础数据结构的基本介绍、常见命令、底层实现、应用场景以及示例,但是由于内容比较多,所以会显得很杂乱,这也是重新修改发布的原因。

本文主要讲解了基础数据结构的基础内容,并没有很深入,关于应用、实现部分的内容,我还是想要单独来写博客讲解,尽量讲清楚。所以,本文其实算是一篇基础的引子,后面要涉及到的其他博客会在后面加上链接。


🎉 如果这篇文章对你有帮助,点赞👍 收藏⭐ 关注✅ 哦,创作不易,感谢!😀 


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

    相关文章:

  • python3GUI--仿崩坏三二次元登录页面(附下载地址) By:PyQt5
  • AIGC视频生成模型:Meta的Emu Video模型
  • 为AI聊天工具添加一个知识系统 之54 为事务处理 设计 基于DDD的一个 AI操作系统 来处理维度
  • 天机学堂5-XxlJobRedis
  • 如何将本地 Node.js 服务部署到宝塔面板:完整的部署指南
  • protobuf: 通讯录3.1
  • 【MCU】CH591用软件 I2C 出现的 bug
  • 我的创作纪念日——我与CSDN一起走过的365天
  • 从Windows通过XRDP远程访问和控制银河麒麟ukey v10服务器,以及多次连接后黑屏的问题
  • 无数据库开源Wiki引擎WikiDocs
  • Spring的Bean:Bean的生命周期(包括实践)
  • CSS实现实现票据效果 mask与切图方式
  • uniapp——App 监听下载文件状态,打开文件(三)
  • RabbitMQ---应用问题
  • 回顾2024年度 - 挑战之旅:学习、生活与成长的华丽蜕变
  • 【无标题】微调是迁移学习吗?
  • Django简介与虚拟环境安装Django
  • leetcode763.划分字母区间
  • Android 存储进化:分区存储
  • 【博客之星2024年度总评选】年度回望:我的博客之路与星光熠熠
  • Android 极光推送快速开发集成指南(1)
  • Grafana系列之Dashboard:新增仪表板、新增变量、过滤变量、变量查询、导入仪表板、变量联动、Grafana Alert
  • 第9章:Python TDD解决货币对象相等性比较难题
  • python爬虫报错日记
  • 初始JavaEE篇 —— 快速上手 SpringBoot
  • 【Redis】Redis 集群中节点之间如何通信?