探索Redis内部数据结构

news2025/2/12 17:42:15

Redis支持多种数据结构,每种数据结构都有其特定的用途。下面对Redis支持的主要数据结构进行详细阐述:

一、字符串(String)

字符串是Redis最基本的数据结构,可以存储一个字符串或者二进制数据,例如图片、序

列化对象等。Redis中的字符串是动态字符串,内部结构实现类似于Java的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配。字符串的最大长度是512M。

字符串是Redis中最基本的数据结构之一,它的底层数据结构被称为简单动态字符串(Simple Dynamic String,SDS)。SDS使用了预分配空间和惰性空间释放等技术,可以在实现高效字符串操作的同时,减少内存的碎片化。

SDS的结构如下所示:

struct sdshdr {
    int len;             // 已使用空间的长度
    int free;            // 可用空间的长度
    char buf[];          // 字节数组
};
+---------+------+------+------+------+------+------+------+------+------+
|  Header | 'R'  | 'e'  | 'd'  | 'i'  | 's'  | '\0' | '3'  | '.'  | '0'  |
+---------+------+------+------+------+------+------+------+------+------+
|  len=6  |   'r'    |   'd'    |    'b'   |    ':'   | '0'    |  '\0'  |  '\0'  |
+---------+------+------+------+------+------+------+------+------+------+
|   free=0  |    R   |    e   |     d  |     i   |     s   |     -    |     1   |      -
+---------+------+------+------+------+------+------+------+------+------+

其中,len表示字符串已经使用的长度,free表示还有多少空间可以用来添加新的字符。buf则是存储字符串的字节数组。

SDS使用了一些技巧来提高性能。例如,在进行字符串扩容时,它会尝试预分配比实际需要更多的空间,以减少内存重分配的次数。此外,SDS还会尽可能地复用已分配的空间,以减少内存碎片。

应用场景:

Redis中的字符串是最基本的数据类型,可以存储任何形式的文本数据,如JSON、HTML、XML、二进制图片等等。字符串在Redis中也是最常用的数据类型之一,常用于缓存数据、计数器、排行榜、存储用户信息等场景。

基本操作:

1、设置字符串:使用SET命令可以将一个字符串设置到Redis中。

SET key value

其中,key表示字符串的键名,value表示字符串的值。

2、获取字符串:使用GET命令可以从Redis中获取一个字符串。

GET key

其中,key表示字符串的键名,返回值为对应的字符串。

3、修改字符串:使用SET命令可以修改Redis中已有的字符串。

SET key value

其中,key表示字符串的键名,value表示新的字符串值。

4、删除字符串:使用DEL命令可以从Redis中删除一个字符串。

DEL key

其中,key表示字符串的键名。

5、获取字符串长度:使用STRLEN命令可以获取一个字符串的长度。

STRLEN key

其中,key表示字符串的键名,返回值为对应字符串的长度。

6、自增或自减操作:使用INCR或DECR命令可以对一个存储整数的字符串进行自增或自减操作。

INCR key
DECR key

其中,key表示字符串的键名,返回值为自增或自减后的值。

7、批量设置字符串:使用MSET命令可以同时设置多个字符串。

MSET key1 value1 key2 value2 ...

其中,key表示字符串的键名,value表示字符串的值,可以设置多个键值对。

8、批量获取字符串:使用MGET命令可以同时获取多个字符串。

MGET key1 key2 ...

其中,key表示字符串的键名,可以获取多个键对应的值。

字符串是Redis中最基本的数据类型,除了上述基本操作,还可以使用各种其他命令对字符串进行操作,例如追加字符串、设置过期时间等。可以根据具体的使用场景和需求,结合Redis提供的命令进行灵活使用。

二、列表(List)

列表是一个双向链表,可以支持在头部和尾部进行插入和删除操作。列表可以用来实现栈和队

列等数据结构。Redis的列表数据结构采用了双向链表实现,每个节点包含一个指向前驱节点和后继节点的指针,以及一个字符串类型的值。同时,列表还包含了一个指向头节点和尾节点的指针,以便快速地进行元素的添加、删除等操作。以下是Redis列表数据结构的结构图:

typedef struct listNode {
    //前置节点
    struct listNode *prev;
    //后置节点
    struct listNode *next;
    //节点的值
    void *value;
} listNode;

在Redis的列表数据结构中,链表节点有两种类型:普通节点和quicklist节点。普通节点用于保存小于64字节的字符串值,而quicklist节点则用于保存大于等于64字节的字符串值或者多个小字符串值。quicklist节点实际上是一个由多个小型ziplist构成的列表,这样能够减少空间的浪费。

应用场景:

  • 作为队列使用:列表数据结构支持在列表的两端进行元素的添加和删除操作,因此可以将其作为队列使用。在生产者消费者模型中,生产者将任务添加到队列中,而消费者则从队列中获取任务进行处理,从而实现任务的异步处理。
  • 作为栈使用:与队列相似,列表数据结构同样支持在列表两端进行元素的添加和删除操作,因此可以将其作为栈使用。在Web开发中,可以利用Redis的列表数据结构保存用户的浏览历史记录,并且能够快速地获取最近浏览的历史记录。
  • 保存关系型数据:在NoSQL数据库中,列表数据结构可以用来保存关系型数据。例如,在社交网络中,可以将关注列表和粉丝列表使用列表数据结构进行存储,从而快速地实现社交网络中的关注、粉丝等功能。

常用操作:

1、LPush(左侧插入元素):将一个或多个元素插入到列表的左侧,如果列表不存在,则创建一个新的列表。

lpush key value1 [value2 ... valuen]

 

2、RPush(右侧插入元素):将一个或多个元素插入到列表的右侧,如果列表不存在,则创建一个新的列表。

rpush key value1 [value2 ... valuen]

3、LPop(左侧删除元素):删除并返回列表左侧的第一个元素。

lpop key

4、RPop(右侧删除元素):删除并返回列表右侧的第一个元素。

rpop key

5、LIndex(获取元素):获取列表中索引位置为index的元素,索引从0开始,负数表示从列表末尾开始计算。

lindex key index

6、LRange(获取范围元素):获取列表中索引位置从start到end的元素,start和end都是0-based,负数表示从列表末尾开始计算。

lrange key start end

7、LLen(获取列表长度):获取列表中元素的数量。

llen key

8、LRem(删除指定数量的元素):从列表中删除与value相等的元素,count表示删除的个数,如果为0表示删除所有匹配的元素,如果为负数表示从列表末尾开始计算。

lrem key count value

9、LTrim(修剪列表):只保留列表中从start到end之间的元素,其余的元素都将被删除,start和end都是0-based,负数表示从列表末尾开始计算。

ltrim key start end

上述操作是Redis列表中的基本操作,还有一些高级操作比如BLPop、BRPop、BRPopLPush等可以满足更多特定的需求。

三、集合(Set)

Set 集合是一个无序的、不允许重复元素的集合,它的底层数据结构使用了「哈希表(Hash Table)」和「跳跃表(Skip List)」的结合体,也就是所谓的「哈希表+跳跃表」。

在 Redis 中,集合类型有两种实现方式:

intset
hashtable

其中,intset 只能存储整型数据,而 hashtable 可以存储任意类型的数据。但是,由于 intset 存储的是连续的整数,因此在存储数值较小、数量较少的集合时,intset 的性能会更好。

对于使用 hashtable 存储的集合来说,其底层数据结构是由一个哈希表和多个链表(或者跳跃表)组成的。其中,哈希表用于存储集合中的元素,链表或跳跃表用于解决哈希冲突。

在 Redis 4.0 之前,Set 集合使用的是哈希表来存储元素,但是在 Redis 4.0 之后,为了提高 Set 集合的查询性能,引入了跳跃表,用于优化有序集合和集合的有序操作。

在 Redis 中,哈希表是一种常用的数据结构,它由一个数组和一些链表(或跳跃表)组成。数组中的每个元素都指向一个链表(或跳跃表),而链表(或跳跃表)则用于解决哈希冲突。当向哈希表中添加元素时,根据元素的哈希值,将元素添加到数组中的相应位置。

在 Set 集合中,每个元素的值作为键存储在哈希表中,而哈希表中的值则都被设置为 NULL。由于哈希表不允许重复键值,因此 Set 集合可以去重。

另外,在 Redis 4.0 中,引入了跳跃表用于优化有序集合和集合的有序操作。跳跃表是一种有序数据结构,它可以快速地进行插入、删除和查找操作,时间复杂度为 O(log n)。在 Set 集合中,跳跃表主要用于优化一些有序操作,例如求交集、并集、差集等操作。

使用场景

  1. 去重:Set能够存储唯一值,因此常用于去重场景。例如统计网站的UV(Unique Visitor)数量,可以将每个用户的IP地址存储在Set中,然后通过Set的元素数量来统计UV。
  2. 集合运算:Set支持并、交、差等集合运算操作,常用于实现共同关注、好友推荐等功能。例如,假设有两个用户A和B,他们的关注列表分别为Set A和Set B,那么A和B共同关注的用户可以通过Set A和Set B的交集来计算。
  3. 排序:Set支持按照元素的大小排序,因此可以将一些带权重的数据存储在Set中,例如用户的积分,然后按照积分大小对用户进行排序。

常用操作

1、添加元素

使用SADD命令向Set中添加元素,如果添加的元素已经存在,则不会重复添加。

SADD key member [member ...]

示例:

127.0.0.1:6379> SADD myset "hello"
(integer) 1
127.0.0.1:6379> SADD myset "world"
(integer) 1
127.0.0.1:6379> SADD myset "hello"
(integer) 0

 

2、获取元素

使用SMEMBERS命令获取Set中的所有元素,返回一个包含所有元素的列表。

SMEMBERS key

示例:

127.0.0.1:6379> SADD myset "hello"
(integer) 1
127.0.0.1:6379> SADD myset "world"
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "hello"
2) "world"

 

3、判断元素是否存在

使用SISMEMBER命令判断元素是否存在于Set中,如果存在返回1,否则返回0。

SISMEMBER key member

示例:

127.0.0.1:6379> SADD myset "hello"
(integer) 1
127.0.0.1:6379> SISMEMBER myset "hello"
(integer) 1
127.0.0.1:6379> SISMEMBER myset "world"
(integer) 0

 

4、获取集合中元素的数量

使用SCARD命令获取Set中元素的数量。

SCARD key

示例:

127.0.0.1:6379> SADD myset "hello"
(integer) 1
127.0.0.1:6379> SADD myset "world"
(integer) 1
127.0.0.1:6379> SCARD myset
(integer) 2

 

5、集合运算

使用SUNION、SINTER、SDIFF命令对Set进行集合运算,分别表示并集、交集、差集。

SUNION key [key ...]
SINTER key [key ...]
SDIFF key [key ...]

示例:

127.0.0.1:6379> SADD set1 "hello"
(integer) 1
127.0.0.1:6379> SADD set1 "world"
(integer) 1
127.0.0.1:6379> SADD set2 "world"
(integer) 1
127.0.0.1:6379> SADD set2 "redis"
(integer) 1
127.0

四、散列(Hash)

在 Redis 中,散列(Hash)是一种特殊的键值对集合,它们是一个字符串类型的 field 和 value 的映射表。Hash 类型非常适合存储对象。比如,一个用户对象可以用一个 Hash 类型来表示,Hash 的 field 可以是用户对象的属性,value 则是属性的值。

Redis 中的 Hash 底层数据结构是一个叫做 ziplist 的双向链表或者 hashtable。ziplist 是一个紧凑的双向链表,可以在内存中快速地进行插入、删除、更新等操作。而 hashtable 是一种基于拉链法的哈希表,可以在内存中快速地进行查找操作。

当 Hash 中的键值对数量较少且每个键值对的键和值都比较短时,Redis 会使用 ziplist 作为底层数据结构。ziplist 的优点是占用的空间比 hashtable 小,缺点是查询和更新速度较慢。

当 Hash 中的键值对数量较多或者键和值比较长时,Redis 会使用 hashtable 作为底层数据结构。hashtable 的优点是查询和更新速度较快,缺点是占用的空间比 ziplist 大。

在 Redis 中,可以使用 HSET 命令往散列中添加键值对,使用 HGET 命令获取散列中指定键的值,使用 HGETALL 命令获取散列中所有键值对的键和值等。由于 Hash 的底层数据结构的特殊性,这些操作的时间复杂度为 O(1)。

常用操作

1、设置散列键值对:使用命令 HSET 可以向散列中添加一个键值对,如果键已经存在,则会将其值覆盖。

HSET key field value

2、获取散列键值对:使用命令 HGET 可以获取散列中指定键的值。

HGET key field

3、获取散列所有键值对:使用命令 HGETALL 可以获取散列中所有的键值对。

HGETALL key

4、删除散列键值对:使用命令 HDEL 可以删除散列中的一个或多个键值对。

HDEL key field [field ...]

5、获取散列所有键或所有值:使用命令 HKEYS 或 HVALS 可以获取散列中所有的键或所有的值。

HKEYS key
HVALS key

使用场景

  1. 用户信息存储:可以使用散列类型来存储用户的个人信息,每个用户对应一个散列,其中键是字段名,值是字段值。
  2. 商品信息存储:可以使用散列类型来存储商品的相关信息,每个商品对应一个散列,其中键是属性名,值是属性值。
  3. 计数器:可以使用散列类型来实现计数器功能,其中键是计数器的名称,值是计数器的值。
  4. 缓存:可以使用散列类型来实现缓存功能,将需要缓存的数据存储在散列中,使用键作为缓存的标识,值作为缓存的内容。

五、有序集合(Sorted Set)

Redis 中有序集合(Sorted Set)的底层数据结构是跳跃表(Skip List)和哈希表(Hash Table)的组合。

在 Redis 中,每个有序集合都对应了一个跳跃表和一个哈希表。其中,跳跃表用来维护有序集合的元素顺序,而哈希表则用来存储元素的值和它们在跳跃表中的位置。

跳跃表是一种随机化数据结构,可以用来实现有序集合和字典等数据结构。跳跃表通过对链表进行随机化扩展,使得其查找、插入和删除操作的时间复杂度都能够达到 O(log n),并且相比于平衡树等其他数据结构,跳跃表的实现简单,运行效率高。

具体来说,跳跃表由多个层级组成,每个层级包含一个链表。链表中的每个节点都包含一个元素值和一个指向下一层节点的指针,以及一个指向相同层级的下一个节点的指针。对于每个节点,其在每个层级的高度都是随机决定的,并且越高层的节点数越少。这样就能够保证跳跃表中的元素顺序是有序的,并且查询、插入和删除操作的时间复杂度都为 O(log n)。

在 Redis 的有序集合中,每个元素都包含一个值和一个分数(Score),分数用来对元素进行排序。Redis 的有序集合支持多个元素具有相同分数的情况,因此每个元素的值都必须是唯一的,但分数可以重复。

常用操作

1、添加元素

可以使用 ZADD 命令添加元素到有序集合中,并指定每个元素的分数,如果元素已经存在,则更新分数。

ZADD key score1 member1 [score2 member2]

例如:

ZADD myzset 10 "redis"

这将在名为 myzset 的有序集合中添加一个值为 "redis",分数为 10 的元素。

2、获取元素

可以使用 ZRANGE 命令获取指定范围内的元素,可以按照分数从小到大排序或从大到小排序。

ZRANGE key start stop [WITHSCORES]

例如:

ZRANGE myzset 0 -1 WITHSCORES

这将返回 myzset 中的所有元素以及它们的分数。

 

3、获取元素数量

可以使用 ZCARD 命令获取有序集合中元素的数量。

ZCARD key

例如:

ZCARD myzset

 

4、获取元素排名

可以使用 ZRANK 命令获取指定元素在有序集合中的排名,排名从 0 开始,按照分数从小到大排序。

ZRANK key member

例如:

ZRANK myzset "redis"

 

5、获取元素分数

可以使用 ZSCORE 命令获取指定元素在有序集合中的分数。

ZSCORE key member

例如:

ZSCORE myzset "redis"

使用场景

1、排行榜

可以使用有序集合存储用户的得分和排名,使用 ZADD 命令添加用户得分,使用 ZREVRANGE 命令按照分数从高到低获取排行榜。

2、计数器

可以使用有序集合存储计数器的值,使用 ZINCRBY 命令增加计数器的值,使用 ZSCORE 命令获取计数器的值。

3、排序

可以使用有序集合存储需要排序的数据,使用 ZADD 命令添加数据,使用 ZRANGE 命令按照分数从小到大排序获取数据。

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

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

相关文章

Echarts—词云库(echarts-wordcloud)配置详解和使用(可自定义形状)

词云库的详解 前言安装基本配置详解具体使用步骤(Vue为例)自定义展示形状 前言 我们经常会看到一些网站或者页面有一堆五颜六色的词汇的聚在一块,有大有小的散落着,看着挺好看的; 也许项目中也会涉及到显示一些关键词…

【Linux脚本篇】Linux循环语句-while

目录 🍁while的语法格式 🍁while循环案例 🍃案例一:输出10-1的降序 🍃案例二:输出10的升序和降序 🍃案例三:批量创建用户 🍁内置跳出循环 🍃案例一&#xff1…

火山引擎 DataLeap:一个易用、高效的数据目录,是如何搭建的?

更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 企业如何找到数据、了解数据以及使用数据? 这离不开数据目录的能力。数据目录有着类似于“字典”的作用,能够帮助数据生产者和使用者快速定位…

ESXI 环境搭建和配置

ESXI 环境搭建和配置 ESXI简介 ESXi专为运行虚拟机、最大限度降低配置要求和简化部署而设计。只需几分钟时间,客户便可完成从安装到运行虚拟机的全过程,特别是在下载并安装预配置虚拟设备的时候。 在VMware Virtual Appliance Marketplace 上有800多款…

RabbitMQ 安装

目录 一、安装RabbitMQ1、Linux 安装⑴、官网rpm包安装①、下载rpm安装包官网下载erlangrabbitmq packagecloud下载erlangrabbitmq ②、安装 erlang③、安装rabbitmq ⑵、packagecloud快速安装⑶、添加用户账号及权限并登陆⑷、卸载erlang与rabbitmq卸载rabbitmq卸载erlang 2、…

积聚产业发展新动能|2023开放原子全球开源峰会OpenAtom OpenHarmony分论坛成功举办

6 月 12 日,以“OpenHarmony 共建开放,共享未来”为主题的 2023 开放原子全球开源峰会 OpenAtom OpenHarmony(以下简称“OpenHarmony”)分论坛在北京北人亦创国际会展中心第一报告厅圆满落幕。开放原子开源基金会理事长孙文龙、华…

【mongoDB数据库基本操作】

mongoDB 基本命令使用 mongoDB数据库基本操作1、连接/创建数据库3、查看数据库4、删除数据库 表的基本操作1、创建表2、删除表3、查询表4、更新表删除表中的记录 mongoDB数据库基本操作 连接mongoDb服务器 进入到mongoDb安装目录 cd /data/mongodb/bin 使用./mongo连接到本…

为什么你的领导,总是挑刺,要求你要有自己的思考?

为什么你的领导,总是挑刺,要求你要有自己的思考? 如何思考?其实有方法论和框架,照这做,也能提升自己的思考能力和维度。 尴尬的问题 在职场的给位是否遇到过这种情况。领导在开完一次沟通会,或…

公元前后的王莽与屋大维

公元元年前后,地球的两端同时产生了两个辉煌的大国,z国和罗马。 我国经历了漫长而又松散的分封制后,在秦帝国时期实现了大一统,在那个时代,因为分封制有效的管理半径最多也就是500公里左右,所以非常不适合…

牛客网1658 页的 Java 岗面试突击手册,GitHub已下载量已过百万

不得不说程序员除了做项目之外,提升自己技能最快的方式就是【看书!】和【刷题!】,这里说的刷题不是无脑刷,而是要明白面试官为什么会问这个问题,以及这个问题的意义在哪里! 今天带来的是全新升…

Beyond Compare 4 正版激活码 -变化是不可避免的,因此,请使用最好的工具对其进行管理。

Beyond Compare 是开发人员、系统管理员和其他人用来比较、合并和同步数据的软件应用程序。它可以在Windows,macOS和Linux上运行。 功能特点 比较文件夹、文件 一、随时随地访问数据 Beyond Compare 是敏捷的。 我们的虚拟文件系统以透明的方式将您连接到您的数据…

Stable Diffusion实操示例

一、负向提示词 解决问题:生成的图片存在瑕疵,比如多只眼睛、多只手指等情况。通过embeddings可以将避免一些常用的不好结果。 方法:从https://civitai.com/?utm_sourcenettsz.com 中下载负向提示词的embeddings模型, EasyNeg…

SOLIDWORKS 2023修复遗漏配合参考及装配体磁力配合

1、修复遗漏的配合参考 ① 为面、边线、平面、轴和点的参考修复遗漏的配合参考 ② 位于与遗漏的参考相同的位置和方向的零部件上选择参考,可修复零 部件遗漏的参考 ③ 包含多个遗漏的配合参考的模型,右键单击配合 文件夹,然后单击自动修复…

AI Expo 2023 | 图技术激活数据资产主题论坛线下报名限时开放!

洞察关联数据 创造无限可能 图技术激活数据资产主题论坛 将于2023年6月25日在苏州召开。 大会背景 本次图技术激活数据资产论坛,由苏州市大数据服务中心协会主办、浙江创邻科技有限公司承办,苏州市计算机学会、苏州市大数据和人工智能产业联盟协办&…

(五) ElasticSearch 数据类型和文档CRUD操作

1.ES数据类型 官方文档地址:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html#_complex_datatypes 核心数据类型(Core Data Types): 核心数据类型是 Elasticsearch 最基本和常用的数据类型…

DataX 3.0 在Windows下基于MySQL做数据迁移示例

在 Windows 安装 Datax: Datax 官网:https://github.com/alibaba/DataX 环境要求: 1:JDK(1.8以上,推荐1.8,并配置好环境变量) 2:Python(网上推荐Python2.…

Java线程的同步机制(synchronized关键字)

线程的同步机制(synchronized ) 1.背景 例子:创建个窗口卖票,总票数为100张.使用实现Runnable接口的方式 * 1.问题:卖票过程中,出现了重票、错票 -->出现了线程的安全问题2.问题出现的原因:当某个线程操作车票的过…

罗马不是一天建成的,那为什么建了那么多罗马?

这一个罗马,那一个罗马,东一个罗马,西一个罗马,世界历史的大半部分都在跟罗马打交道。更要命的是四大文明古国还没有古代罗马。 存在感这么强,还不是四大文明古国,名字还难记,公元前居然就有共…

P19[6-7]编码器接口(硬)

编码器接口自动控制定时器时基单元中的CNT计数器进行自增或自减,(初始化后CNT=0;编码器右转,产生一个脉冲,CNT++,左转,产生一个脉冲,CNT--)。相当于外部时钟,同时控制CNT计数方向和计数时钟。每隔一段时间取CNT的值,再把CNT清零,就表示编码器的速度。 编码器测速即测频法…

总结linux查看当前用户的方法

操作环境:ubuntu 18.04系统 一、查看当前用户 1、shell终端中输入:who 当前用户为:root,使用pts的终端,后面是登陆的时间 2、shell终端中输入:whoami 当前用户为:root,很精简输出结果…