Redis常用数据结构及原理

Redis常用六种数据类型

Redis 支持多种数据类型,每种类型都具有不同的特性和用途。以下是 Redis 中常见的数据类型:

一、字符串(String)

1、基本介绍

字符串是最基本的数据类型,可以存储任意类型的数据,如文本、数字或序列化对象。可以使用字符串相关的命令对其进行操作,如设置值(SET)、获取值(GET)、增加数值(INCR)、追加字符串(APPEND)等。

2、底层数据结构和原理

在 Redis 中,字符串类型的底层数据结构和原理是简单动态字符串(SDS,Simple Dynamic String)。

简单动态字符串是 Redis 自己实现的一种字符串结构,相比于传统的 C 字符串(以空字符 ‘\0’ 结尾的字符数组),简单动态字符串具有以下优势:

  • O(1) 时间复杂度的修改操作:简单动态字符串通过维护字符串长度和可用空间的变量,可以在 O(1) 时间复杂度内进行字符串的修改操作,而不需要像传统 C 字符串那样进行内存拷贝和分配。

  • 动态扩容和缩容:简单动态字符串在需要扩容时,可以按需动态地增加内存空间,而不是事先分配固定大小的缓冲区。这种动态扩容的机制使得字符串的长度可以根据需要进行自由调整,节省了内存空间。

  • 二进制安全:简单动态字符串可以存储任意二进制数据,不仅仅限于文本字符串。这使得 Redis 可以在字符串类型中存储和处理二进制数据,而不会受到 C 字符串的限制。

  • 内存预分配和惰性空间释放:简单动态字符串在进行扩容时,会预先分配一定的额外空间,以减少频繁的内存分配操作。同时,在字符串缩短时,不会立即释放多余的空间,而是保留一部分空间,以备后续使用,从而提高了性能。

总之,简单动态字符串是 Redis 中字符串类型的底层数据结构,通过动态扩容和缩容、O(1) 时间复杂度的修改操作等特性,提供了高效的字符串操作。这种数据结构使得 Redis 的字符串类型非常适用于存储和处理各种类型的数据,包括文本和二进制数据。

这个其实和Java中的ArrayList的实现比较像,ArrayList使用的是动态数组。如果读者比较感兴趣的话,后续我可以单独写一篇文章来着重讲述两者的区别。

二、哈希(Hash)

1、基本介绍

哈希是一种键值对集合,类似于对象或字典。每个哈希可以存储多个字段和对应的值。可以使用哈希相关的命令对其进行操作,如设置**字段值(HSET)、获取字段值(HGET)、获取全部字段和值(HGETALL)**等。

2、底层数据结构和原理

在 Redis 中,Hash(哈希)的底层数据结构是哈希表(Hash Table)。

哈希表是一种基于键值对的数据结构,通过哈希函数将键映射到存储位置,实现了高效的键值查找和插入操作。在 Redis 的哈希中,哈希表被用来存储哈希的键值对。

Hash大家应该都比较熟悉了,这里简单讲一下Redis 中哈希底层数据结构和原理的一些关键点:

  • 哈希表优势:使用哈希表作为哈希的底层数据结构有几个优势。首先,通过哈希表,可以以常数时间复杂度 O(1) 来执行插入、删除和查找操作。其次,哈希表可以高效地处理大量的键值对数据,具有良好的扩展性。

  • 哈希表存储键值对:在 Redis 中,每对哈希的键值对被存储为哈希表的键值对。哈希表的键被称为字段(field),而哈希表的值被称为值(value)。通过哈希表的键,可以快速检索和操作哈希中的键值对。

  • 哈希表的键冲突处理:由于哈希函数的输出空间有限,不同的键可能映射到相同的哈希表位置,这就是所谓的键冲突。为了解决键冲突,Redis 使用链地址法(Separate Chaining)来处理相同哈希值的键。具体来说,Redis 将具有相同哈希值的键值对放在同一个链表中,通过链表来存储冲突的键值对。

  • 哈希表的扩容和缩容:为了保持哈希表的高效性能,Redis 在哈希表达到一定负载因子时会自动进行扩容操作。扩容操作涉及重新计算哈希函数和重新分配空间,以便保持较低的键冲突率。同样,当哈希表的使用率较低时,Redis 会自动进行缩容操作,以节省内存空间。

  • 哈希的常用操作:Redis 提供了一系列命令来操作哈希,如添加字段和值(HSET)、获取值(HGET)、删除字段(HDEL)等。这些命令通过操作底层的哈希表来实现哈希的操作。

Redis 中的哈希数据类型通过使用哈希表作为底层数据结构,实现了高效的键值查找和插入操作。这种数据结构使得 Redis 的哈希非常适用于存储和操作具有键值对结构的数据,如用户信息、配置信息等。

三、列表(List)

1、基本介绍

列表是一个有序的字符串元素集合,可以在列表的两端进行插入或删除操作。列表可以用作队列或栈。您可以使用列表相关的命令对其进行操作,如插入元素到列表头(LPUSH)、弹出列表尾部元素(RPOP)、获取指定范围的元素(LRANGE)等。

2、底层数据结构和原理

在 Redis 中,List(列表)的底层数据结构是双向链表(doubly linked list)。(注:Java中的LinkedList底层也是双向链表,可以对比学习。)

双向链表是一种由多个节点组成的数据结构,每个节点包含一个值和两个指针,分别指向前一个节点和后一个节点。在 Redis 中,每个列表都由一个双向链表来实现,列表的每个元素都存储在一个节点中。

Redis 通过使用双向链表作为列表的底层数据结构,实现了对列表的高效操作。以下是一些关于 Redis 列表底层数据结构和原理的重要细节:

  • 双向链表优势:使用双向链表作为列表的底层数据结构有几个优势。首先,它允许在列表的两端进行高效的插入和删除操作,时间复杂度为 O(1)。其次,双向链表可以按照顺序遍历和反向遍历列表,使得在有序列表中执行范围操作非常高效。

  • 列表的头节点和尾节点:Redis 中的列表有一个特殊的头节点和尾节点,分别表示列表的开头和结尾。这些节点不包含实际的值,只是作为指示列表边界的标记。它们的存在使得在列表两端执行插入和删除操作更加高效。

  • 列表的节点结构:每个列表节点包含三个主要部分。第一个部分是前置节点指针,指向前一个节点;第二个部分是后置节点指针,指向后一个节点;第三个部分是值,存储实际的列表元素。

  • 列表的头指针和尾指针:Redis 中的列表有两个指针,分别指向列表的头节点和尾节点。这些指针使得在列表两端执行插入、删除和访问操作更加方便和高效。

  • 列表的常用操作:Redis 提供了一系列命令来操作列表,如插入元素到列表头部(LPUSH)、插入元素到列表尾部(RPUSH)、从列表头部弹出元素(LPOP)、从列表尾部弹出元素(RPOP)等。这些命令通过操作双向链表的节点来实现列表的操作。

Redis 中的列表数据类型通过使用双向链表作为底层数据结构,实现了高效的插入、删除和访问操作。这种数据结构使得 Redis 列表非常适用于队列、栈、任务列表等应用场景,同时提供了丰富的命令和操作来满足不同的需求。

四、集合(Set)

1、基本介绍

集合是一组唯一的、无序的字符串元素集合。集合支持添加、删除和判断元素是否存在的操作。您可以使用集合相关的命令对其进行操作,如添加元素到集合(SADD)、删除元素(SREM)、判断元素是否存在(SISMEMBER)等。

2、底层数据结构和原理

在 Redis 中,Set(集合)的底层数据结构是哈希表(Hash Table)。

哈希表是一种基于键值对的数据结构,它通过哈希函数将键映射到存储位置,从而实现高效的键值查找和插入操作。在 Redis 的集合中,哈希表被用来存储集合的元素。

以下是 Redis 中集合底层数据结构和原理的一些关键点:

  • 哈希表优势:使用哈希表作为集合的底层数据结构有几个优势。首先,通过哈希表,可以以常数时间复杂度 O(1) 来执行插入、删除和查找操作。其次,哈希表可以高效地处理大量的键值对数据,具有良好的扩展性。

  • 哈希表存储集合元素:在 Redis 中,每个集合元素被存储为哈希表的键,而哈希表的值则被设置为一个固定的空占位符。通过哈希表的键,可以快速检索和操作集合中的元素。

  • 哈希表的键冲突处理:由于哈希函数的输出空间有限,不同的键可能映射到相同的哈希表位置,这就是所谓的键冲突。为了解决键冲突,Redis 使用链地址法(Separate Chaining)来处理相同哈希值的键。具体来说,Redis 将具有相同哈希值的键放在同一个链表中,通过链表来存储冲突的键值对。

  • 哈希表的扩容和缩容:为了保持哈希表的高效性能,Redis 在哈希表达到一定负载因子时会自动进行扩容操作。扩容操作涉及重新计算哈希函数和重新分配空间,以便保持较低的键冲突率。同样,当哈希表的使用率较低时,Redis 会自动进行缩容操作,以节省内存空间。

  • 集合的常用操作:Redis 提供了一系列命令来操作集合,如添加元素到集合(SADD)、从集合中移除元素(SREM)、判断元素是否存在于集合中(SISMEMBER)等。这些命令通过操作底层的哈希表来实现集合的操作。

Redis 中的集合数据类型通过使用哈希表作为底层数据结构,实现了高效的插入、删除和查找操作。这种数据结构使得 Redis 集合非常适用于存储和操作唯一值的场景,并提供了丰富的命令和操作来满足不同需求。

五、有序集合(Sorted Set)

1、基本介绍

有序集合是一种在集合基础上增加了一个分数(score)的数据结构。每个元素都有一个唯一的值和一个对应的分数,通过分数可以对元素进行排序。您可以使用有序集合相关的命令对其进行操作,如添加元素到有序集合(ZADD)、根据分数范围获取元素(ZRANGEBYSCORE)、获取指定排名范围的元素(ZRANGE)等。

2、底层数据结构和原理

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

跳跃表是一种有序数据结构,类似于链表,但在每个节点中添加了多个指向其他节点的指针,从而实现高效的查找和范围操作。哈希表用于存储每个成员及其对应的分数。

以下是 Redis 中有序集合底层数据结构和原理的一些关键点:

  • 跳跃表:有序集合使用跳跃表作为有序数据的主要存储结构。跳跃表中的每个节点都包含一个成员和一个分数,节点按照成员的字典序进行排序。通过多个层级的指针,跳跃表可以快速跳过一些节点,从而加快查找速度。

  • 跳跃表的层级:跳跃表由多个层级组成,每个层级都是一个有序链表。最底层是包含所有成员的完整链表,而上层则是通过“跳跃”的方式连接较少的节点。这种层级结构使得在跳跃表中查找成员的时间复杂度为 O(log n)。

  • 哈希表:除了跳跃表,Redis 还使用哈希表来存储每个成员及其对应的分数。哈希表通过将成员作为键、分数作为值来存储数据。这样,当需要根据成员进行查找或更新时,可以通过哈希表快速定位到对应的节点。

  • 跳跃表和哈希表的结合使用:通过将跳跃表和哈希表结合使用,Redis 实现了有序集合数据类型的高效操作。跳跃表提供了快速的有序查找和范围操作,而哈希表则提供了快速定位成员的能力。

  • 有序集合的常用操作:Redis 提供了一系列命令来操作有序集合,如添加成员和分数(ZADD)、根据分数范围获取成员(ZRANGEBYSCORE)、获取成员的排名(ZRANK)等。这些命令通过操作底层的跳跃表和哈希表来实现有序集合的操作。

Redis 中的有序集合数据类型通过使用跳跃表和哈希表的结合,实现了高效的有序集合操作。跳跃表提供了快速的查找和范围操作,而哈希表提供了快速定位成员的能力。这种数据结构使得 Redis 有序集合非常适用于实现排行榜、计数器和范围查询等应用场景。

六、Bitmaps

1、基本介绍

位图是一种使用二进制位来存储和操作数据的数据结构。您可以使用位图相关的命令对其进行操作,如设置位(SETBIT)、获取位(GETBIT)、对多个位进行逻辑操作(BITOP)等。

除了以上常见的数据类型,Redis 还支持其他数据类型,如地理位置(Geospatial)、流(Stream)等。每种数据类型都有各自的用途和适用场景,您可以根据具体的需求选择合适的数据类型来存储和操作数据。

2、底层数据结构和原理

在 Redis 中,Bitmaps(位图)的底层数据结构是字符串(String)。

字符串是 Redis 中最基本的数据结构,可以存储二进制数据。在 Bitmaps 中,每个位(bit)都被存储为字符串中的一个字符,可以表示为 0 或 1。Redis 使用字符串来表示位图,并提供了一系列命令来操作位图数据。

以下是 Redis 中位图底层数据结构和原理的一些关键点:

  • 字符串存储位:在 Redis 中,每个位都由一个字符来表示。位图使用 0 或 1 来表示位的状态,通常使用字符 “0” 和 “1” 分别表示位值为 0 或 1。

  • 字符串的位操作:Redis 提供了一些位操作命令,如设置位(SETBIT)、获取位(GETBIT)、对多个位进行逻辑操作(BITOP)等。这些命令通过操作字符串的位来实现位图的操作。

  • 字符串的二进制存储:Redis 使用字节序列来存储字符串,每个字节可以表示 8 个位。位图中的每个位会转换成对应字节中的某一位。

  • 位图的大小:Redis 中的位图可以非常大,可以有 2^32 = 4294967296 个位,即可以表示一个长度为 4294967296 的位序列。

  • 位图的应用:位图在 Redis 中广泛应用于各种场景,如统计在线用户、记录用户行为、判断某个元素是否存在等。由于位图的存储非常紧凑,可以有效地节省存储空间。

请注意,位图虽然非常高效,但它是以整个字符串作为单位进行操作的,如果只需要操作其中的某些位,可能会涉及到整个字符串的读取和写入,可能会对性能产生影响。因此,在使用位图时,需要根据实际需求和数据规模进行权衡和设计。

除了以上常见的数据类型,Redis 还支持其他数据类型,如地理位置(Geospatial)、流(Stream)等。每种数据类型都有各自的用途和适用场景,可以根据具体的需求选择合适的数据类型来存储和操作数据。

欢迎关注我的公众号,除了分享一些技术文章,还会分享一些工作经验和有趣的事。
请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大骨熬汤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值