Redis基本数据结构

1、基本数据结构

  • String(字符串)

  • List(列表)

  • Hash(哈希)

  • Set(集合)

  • Sorted Set(有序集合)

    上面都是Redis键值对中值的数据类型,也就是数据的保存形式。

     

2、底层数据结构

底层数据结构一共有6种,分别是简单动态字符串双向链表压缩列表哈希表跳表整数数组

3、键和值本身用什么结构组织?

为了实现从键到值的快速方法,Redis使用了一个哈希表来保存所有的键值对。

一个哈希表,其实就是一个数组,数组的每个元素称为一个哈希桶。一个哈希表是由多个哈希桶组成的,每个哈希桶中保存键值对数据。

哈希桶中的元素保存的并不是值本身,而是指向具体值的指针。不管值是String还是集合类型,哈希桶中的元素都是指向它们的指针。

4、哈希冲突

哈希桶的个数通常要少于Key的数量,两个Key的哈希值和哈希桶计算对应关系的时候,正好落在了同一个哈希桶中。

解决方式:链式哈希。即同一个哈希桶中的多个元素用一个链表来保存,它们之间依次用指针来连接。

带来的新问题:因此哈希冲突链上的元素只能通过指针逐一查找再操作,如果哈希表中写入的数据越来越多,哈希冲突也会越来越多,那么就会导致某些哈希冲突链会越来越长,影响查找效率。

解决方式:哈希表rehash

 

5、哈希表rehash

增加现有的哈希桶数量,让逐渐增多的entry元素在更多的哈希桶中分散保存,从而减少当个哈希桶中元素的数量,从而减少单个哈希桶的冲突。

操作方式:Redis默认采用了两个全局哈希表:哈希表1和哈希表2。一开始插入数据的时候,默认使用哈希表1,此时哈希表2并没有分配空间。随着数据的增多,Redis开始执行rehash。

步骤:

  1. 给哈希表2分配更大的空间,比如是当前哈希表1大小的2倍。

  2. 把哈希表1中的数据重新映射并拷贝到哈希表2。

  3. 释放哈希表1的空间,留作下一次rehash扩容备用。

     

问题:因为涉及到大量的数据拷贝,如果一次性的把哈希表1中的数据都迁移完成,会造成Redis的线程阻塞。

解决方式:渐进式rehash

6、渐进式rehash

在第二步拷贝数据的时候,Redis仍然正常处理客户端的请求,每处理一个请求时,从哈希表1中的第一个索引位置开始,顺带着将这个索引位置上的所有的entries拷贝到哈希表2中。等处理下一个请求时,再顺带着拷贝哈希表1中的下一个索引位置的entries,依次操作,这样把一次性大量拷贝的开销,分摊到了多次处理请求的过程中,保证数据访问速度。

7、集合类型的底层数据结构和操作复杂度

集合类型的底层数据结构主要有5种:整数数组、双向链表、哈希表、跳表、压缩列表

压缩列表:类似一个数组,数据中的每一个元素都对应保存一个数据。和数组不同的是,压缩列表在表头有三个字段:zlbytes、zltail和 zllen,分别表示列表长度、列表尾的偏移量和列表中entry的个数,在表尾还有一个zlend,表示列表结束。如果要查找第一个元素和最后一个元素,通过表头的三个字段的长度直接定位,复杂度为O(1),其他元素只能逐个查找,复杂度为O(N)。

跳表:在链表的基础上,增加了多级索引,通过索引位置的几个跳转,实现数据的快速定位。

8、数据结构的时间复杂度

名称时间复杂度
哈希表O(1)
跳表O(logN)
双向链表O(N)
压缩列表O(N)
整数数组O(N)

9、不同操作的复杂度

主要是针对集合类型的操作

  1. 每一种集合类型对单个数据实现的增删改查操作是最基础的

  2. 范围操作,即对集合的遍历操作,可以返回集合中的所有元素。此类操作的复杂度一般是O(N),比较耗时,应该尽量避免。Redis2.8版本开始提供了渐进式的SCAN遍历操作,每次只返回有限数量的数据。

  3. 统计操作,即集合类型对集合中所有元素个数的记录。因集合类型采用压缩列表、双向链表、整数数组这些数据结构,结构中专门记录了元素的个数统计,通常是高效的。

  4. 压缩列表和双向链表都会记录表头和表尾的偏移量,因此对于List 类型的LPOP,RPOP,LPUSH,RPUSH四个操作来说,比较高效。可以用于FIFO队列的场景

参考资料:https://time.geekbang.org/column/article/268253 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

DreamCatcher

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

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

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

打赏作者

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

抵扣说明:

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

余额充值