Redis核心技术及实战(二.数据结构)

二:Redis为什么这么快?=> 数据结构

原文:《02丨数据结构:快速的Redis有哪些慢操作?》

为什么这么快?一是因为内存存储,二是因为其数据结构,三是多路复用机制(下一节讲)。

Redis使用Hash表来保存所有的键值对,Key为String类型,Value为五种数据形式,每一种数据形式都有其对应的底层结构,除String类型外的4种数据类型又称为集合数据。

image-20220511192453348

Note:Redis还有三种扩展数据类型,BitMap、HyperLogLog、GEO,这三种在后面十一、十二节介绍。

1. 全局哈希表

一个哈希表就是一个数组,每个元素称为一个哈希桶,即一个entry,其中存储了key和value指针,分别指向键和值。

image-20220511192926019

哈希表的查询速度是O(1),但是为什么往Redis中写入大量数据后会变慢呢?因为哈希表的哈希冲突和rehash可能带来阻塞操作

如何解决哈希冲突? => 链式哈希、rehash

**(1)链式哈希:**一个哈希桶中的多个元素用同一个链表来保存,它们之间用指针连接。但是,链式存储的查询操作太慢,所以使用rehash

**(2)rehash:**增加现有的哈希桶的数量,让逐渐增多的entry元素能在桶之间分散开来。为了使rehash操作更高效,Redis默认使用了两个全局哈希表,一开始使用全局哈希表1(哈希表2没有分配空间),当数据量变大时,开始执行rehash:

  • 给全局哈希表2分配更大的空间,比如是哈希表1的两倍;
  • 把哈希表1的数据重新映射拷贝到哈希表2中去;
  • 释放哈希表1的空间,留作下次rehash扩容备用。

这里有一个问题,就是第二步中把数据全部拷贝过去到哈希表2中,由于数据量太大,会造成阻塞时间过久。 => 渐进式rehash

**(3)渐进式rehash:**在第二步拷贝数据时,Redis仍然正常处理客户端请求,每处理一次请求,就从哈希表1中的第一个索引位置开始,将这个索引位置上的所有entries拷贝到哈希表2中,等待下一次请求时,再继续拷贝下一个索引位置的entries…如此一来就把一次性大量拷贝开销给分摊给了多次请求中,加快了速度。 (如果一直没有请求,Redis也会定时进行渐进式rehash操作)

image-20220511194355861

2. 集合数据操作效率

image-20220511195043999

​ 集合数据类型的底层结构有五种:双向链表、整数数组、哈希表、压缩列表、跳表,其中前三者比较常见,就不再解释。主要是后面两种,压缩列表和跳表。

**压缩列表:**类似于一个数组,只不过表头有三个字段zlbytes、zltail、zllen,分别表示列表长度、列表尾的偏移量、列表中entry的个数;表尾有一个字段zlend表示列表结束。我们要查找首尾元素,就直接可以通过头部三个字段确定,为O(1),但是其它元素的查找是O(n)。

image-20220511200506200

**跳表:**对有序链表的改进,增加了多级索引,通过索引位置的几个跳转实现数据的快速定位。

image-20220511200600332

各数据结构的时间复杂度:

image-20220511200628645

各操作的时间复杂度:

  • 单元素操作:如Hash类型的HGET、HSET,Set类型的SADD、SREM等,这些操作的时间复杂度由集合采用的数据结构决定,比如采用哈希表时,为O(1)(如果是操作多个元素,如HMGET,时间复杂度由操作元素个数决定);
  • 范围操作:集合中的遍历操作,返回所有/部分数据,如Hash类型的HGETALL和Set类型的SMEMBERS为返回所有数据,List类型的LRANGE和ZSet类型的ZRANGE,这些操作都是O(N),我们应该尽量避免(SCAN操作为渐进式遍历,可以避免阻塞严重)。
  • 统计操作:返回元素个数,如LLEN、SCARD,由于双向链表、压缩列表、整数数组都有记录元素个数,为O(1)
  • 特殊情况:比如压缩列表和双向链表都会记录首尾位置,对应List类型的LPOP、LPUSH、RPOP、RPUSH操作都为O(1),所以List类型可以用在FIFO的场景中。

整数数组和压缩列表作为底层数据结构的优点是什么? => 两者都是连续存储,元素一个挨一个,非常紧凑,省内存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值