Redis数据结构

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

 

String 类型的底层实现只有一种数据结构,也就是简单动态字符串。而 List、Hash、Set 和 Sorted Set 这四种数据类型,都有两种底层实现结构。通常情况下,我们会把这四种类型称为集合类型,它们的特点是一个键对应了一个集合的数据

 

为了实现从键到值的快速访问,Redis 使用了一个哈希表来保存所有键值对。一个哈希表,其实就是一个数组,数组的每个元素称为一个哈希桶。一个哈希表是由多个哈希桶组成的,每个哈希桶中保存了键值对数据。哈希桶中的元素保存的并不是值本身,而是指向具体值的指针。这也就是说,不管值是 String,还是集合类型,哈希桶中的元素都是指向它们的指针。

https://qiankunli.github.io/public/upload/storage/redis_kv.png

         如上所示,哈希桶中的 entry 元素中保存了*key和*value指针,分别指向了实际的键和值,这样一来,即使值是一个集合,也可以通过*value指针被查找到。

         这个哈希表保存了所有的键值对,称为全局哈希表。我们只需要计算键的哈希值,就可以知道它对应的哈希桶的位置,然后可以访问响应的entry元素。

 

Rehash

      哈希表查找键值对虽然快,但是久而久之也无法避免哈希值冲突的问题,所以有了rehash的过程,总的来说分为三步:

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

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

3. 释放哈希表 1 的空间。

其中第二步涉及到了大量的数据拷贝,可能会造成redis阻塞,为了避免这个问题,redis使用了渐进式rehash。

  1. 拷贝的时候,Redis 仍然正常处理客户端请求,每处理一个请求时,从哈希表 1 中的第一个索引位置开始,顺带着将这个索引位置上的所有 entries 拷贝到哈希表 2 中;

  2. 等处理下一个请求时,再顺带拷贝哈希表 1 中的下一个索引位置的entries。

  3. 重复1、2直到拷贝完成,这样就把一次打的拷贝,分摊到多出请求处理的过程中。

 

底层数据结构介绍

如上所示,底层的数据结构有6种,简单动态字符串、双向链表、压缩列表、哈希表、跳表和整数数组。其他几种比较常见,下面只说说压缩列表和跳表。

压缩列表

压缩列表实际上类似于一个数组,数组中的每一个元素都对应保存一个数据。和数组不同的是,压缩列表在表头有三个字段 zlbytes、zltail 和 zllen,分别表示列表长度、列表尾的偏移量和列表中的 entry 个数;压缩列表在表尾还有一个 zlend,表示列表结束。

如果我们要查找定位第一个和最后一个元素,可以通过表头三个字段的长度直接定位,复杂度是 O(1)。而查找其他元素时,只能逐个查找,此时的复杂度是 O(N)。

 

跳表

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

当数据量很大时,跳表的查找复杂度就是 O(logN)。

 

不同操作的复杂度

  • 单元素操作,是指每一种集合类型对单个数据实现的增删改查操作。例如,Hash 类型的 HGET、HSET 和 HDEL,Set 类型的 SADD、SREM、SRANDMEMBER 等。这些操作的复杂度由集合采用的数据结构决定,例如,HGET、HSET 和 HDEL 是对哈希表做操作,所以它们的复杂度都是 O(1);
  • 范围操作,是指集合类型中的遍历操作,可以返回集合中的所有数据,比如 Hash类型的 HGETALL 和 Set 类型的 SMEMBERS,或者返回一个范围内的部分数据,比如 List类型的 LRANGE 和 ZSet 类型的 ZRANGE。这类操作的复杂度一般是 O(N),比较耗时。不过,Redis 从 2.8 版本开始提供了 SCAN 系列操作(包括 HSCAN,SSCAN 和ZSCAN),这类操作实现了渐进式遍历,每次只返回有限数量的数据。
  • 统计操作,是指集合类型对集合中所有元素个数的记录,例如 LLEN 和 SCARD。这类操作复杂度只有 O(1),这是因为当集合类型采用压缩列表、双向链表、整数数组这些数据结构时,这些结构中专门记录了元素的个数统计。
  • 例外情况,是指某些数据结构的特殊记录,例如压缩列表和双向链表都会记录表头和表尾的偏移量。这样一来,对于 List 类型的 LPOP、RPOP、LPUSH、RPUSH 这四个操作来说,它们是在列表的头尾增删元素,这就可以通过偏移量直接定位,所以它们的复杂度也只有 O(1)。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值