Redis作为内存数据库,访问速度快是最大的特点,那么,什么情况下,Redis也会变慢呢?

Redis底层数据结构

Redis有5种基本数据类型:String,List,Hash,Set,ZSet

有6种底层数据结构:

  • 简单动态字符串SDS
  • 压缩列表 ZipList
  • 快表 QuickList
  • 字典/哈希表 Dict
  • 整数集 IntSet
  • 跳表 ZSkipList

键值访问

Redis用了一个全局的哈希表保存所有的键值对,一个哈希表,其实是一个数组,数组里的每一个元素对应为一个哈希桶。每个哈希桶保存键值对数据。

哈希桶中元素保存的是指向值的地址指针,这样即使值是一个集合,也能通过指针找到。

如图是全局哈希表的键值访问过程:

哈希表的查找依赖哈希计算,O(1)的时间复杂度找到键值对。

为什么哈希表操作变慢了?

既然是哈希表,可能存在哈希冲突。redis解决哈希冲突的方法是链地址法,即同一个哈希桶中的多个元素用一个链表来保存,它们之间用指针相连。

看到这,肯定有个疑问,如果冲突的元素越来越多,就会导致在这个链上查找的耗时变长,对于追求快的Redis来说,这是不能接受的。

所以,Redis会对哈希表做rehash操作。可以理解为和Java里的HashMap扩容一样。增加现有哈希桶数量,让增多的元素在更多的桶之间分散保存。

redis中rehash的方法是:

1. redis默认使用了2个全局哈希表
2. 当插入数据时,默认使用哈希表1
3. 随着数据增多,redis进行rehash操作,为哈希表2分配更大的内存空间,如是哈希表1的两倍;
4. 把哈希表1中的数据重新映射到哈希表2中
5. 释放哈希表1的内存

其中 数据重新映射 这一步涉及大量数据拷贝,如果让主线程一次全部迁移完,会造成redis线程阻塞。

为了避免这一问题,redis使用了渐进式rehash

简单地说,就是在拷贝数据过程中,不是一次拷贝完。而是每处理一个请求时,从哈希表1的第一个索引位置开始,将这个位置上所有元素拷贝到哈希表2中,等处理下一请求时,再拷贝下一索引位置的数据,整个过程如下:

集合数据结构的操作

集合类型的底层结构是:整数数组,双向链表,哈希表,压缩列表,跳表

哈希表、整数列表、双向链表的操作特征都是顺序读写,操作复杂度是O(N),效率比较低。

压缩列表:

  • 类似数组,表头有3个字段zlbytes、zltail、zllen,分别表示列表长度、列表尾的偏移量、列表中entry个数。
  • 表尾还有一个zlend,表示列表结束

查找定位列表的第一个元素和最后一个元素,可以通过表头3个字段的长度直接定位,复杂度O(1),查找其他元素时,只能逐个查找了,复杂度O(N)。

跳表

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

如图所示,

  • 单链表查找元素33,需要找6次;
  • 增加一级索引(每两个元素选一个出来作为索引,索引再通过指针指向原始链表),只需要找4次;
  • 增加二级索引(从一级索引中再抽取部分元素作为二级索引),只需要找3次;

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

redis底层数据结构查找的时间复杂度如下表:

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

思考:压缩列表和整数数组的查找时间复杂度比较高,为什么redis还要用它们呢?

  • 内存利用率

    数组和压缩列表都是非常紧凑的数据结构,比起链表,占用的内存更少,而redis是内存数据库,需要尽可能的优化,提高内存利用率;

  • 数组对CPU高速缓存支持更友好

Redis有哪些潜在的慢操作?的更多相关文章

  1. Redis:安装、配置、操作和简单代码实例(C语言Client端)

    Redis:安装.配置.操作和简单代码实例(C语言Client端) - hj19870806的专栏 - 博客频道 - CSDN.NET Redis:安装.配置.操作和简单代码实例(C语言Client端 ...

  2. redis对sorted_set进行的相关操作

    redis对sorted_set(有序集合)类型操作的相关命令以及如何在python使用这些命令 redis对sorted_set(有序集合)类型操作的命令: 命令 语法 概述 返回值 Redis Z ...

  3. Redis 安装,配置以及数据操作

    Nosql介绍 Nosql:一类新出现的数据库(not only sql)的特点 不支持SQL语法 存储结构跟传统关系型数据库中那种关系表完全不同,nosql中存储的数据都是k-v形式 Nosql的世 ...

  4. redis基础之基本键值操作和使用(三)

    前言 redis安装完毕后开始使用redis,先熟悉命令行操作. redis数据的类型 键:redis的所有的键都是string类型: 值:五种类型 string:字符串类型:一个string最大可以 ...

  5. redis的String类型以及其操作

    Redis的数据类型 String类型以及操作 String是最简单的数据类型,一个key对应一个Value,String类型是二进制安全的.Redis的String可以包含任何数据,比如jpg图片或 ...

  6. 在centos7中安装redis,并通过node.js操作redis

    引言 最近在学习node.js 连接redis的模块,所以尝试了一下在虚拟机中安装cent OS7,并安装redis,并使用node.js 操作redis.所以顺便做个笔记. 如有不对的地方,欢迎大家 ...

  7. Redis数据类型Strings、Lists常用操作指令

    Redis数据类型Strings.Lists常用操作指令 Strings常用操作指令 GET.SET相关操作 # GET 获取键值对 127.0.0.1:6379> get name (nil) ...

  8. Redis数据类型:Hashes、Geo操作指令

    Redis数据类型:Hashes.Geo操作指令 Hashes常用操作指令 Redis Hashes是一个键值对的映射表,最对能存储2^32-1(约40亿)个键值对. HSET HGET HSET:将 ...

  9. Redis的C++与JavaScript访问操作

    上篇简单介绍了Redis及其安装部署,这篇记录一下如何用C++语言和JavaScript语言访问操作Redis 1. Redis的接口访问方式(通用接口或者语言接口) 很多语言都包含Redis支持,R ...

  10. redis常用的命令行以及操作

    redis常用的命令行以及操作 转载酱紫人的理直气壮 最后发布于2018-07-30 17:00:41 阅读数 805  收藏 转载地址:https://blog.csdn.net/li_lening ...

随机推荐

  1. Java 开发手册 (阿里巴巴开发手册)

    Java 开发手册 (有需要pdf版本的私信我,可以邮箱发)0版本号 制定团队 更新日期 备注 1.4.0 阿里巴巴集团技术团队 2018.5.20 增加设计规约(详尽版) 一.编程规约 (一) 命名 ...

  2. package.json文件中版本号

    "5.0.3"表示安装指定的5.0.3版本,"-5.0.3"表示安装5.0.X中最新的版本,"^5.0.3"表示安装5.X.X中最新的版本.

  3. 黑马vue学习笔记

    1.v-model原理 2.数组相关API 3.prop命名规则: 4.非父子组件传值-事件中心

  4. java进阶(28)--Map集合

    一.Map简介: 1.Map与collection没有继承关系 2.Map集合以key与value的方式存储数据   二.常用方法: 1.void clear():清空Map集合

  5. 深入理解Kafka核心设计及原理(一):初识Kafka

    转载请注明出处: 1.1 kafka简介 Kafka 起初是由 Linkedin 公司采用 Scala 语言开发的一个多分区.多副本且基于 ZooKeeper协调的分布式消息系统,现己被捐献给 Apa ...

  6. 本地打包编译jdk版本问题

    一.遇到的问题 进行项目接入pinpoint-ice插件,启动项目时pinpoint-agent日志报如下不支持jdk8的错误.'   二.排查 我们是在个人笔记本电脑上windows环境下通过mav ...

  7. 使用ProjectQ生成量子算法指令集

    技术背景 所谓的指令集,按照字面意思来理解就是计算机底层允许使用的操作指令的集合.在量子计算机领域,由于实现方案的不同,在不同的体系内的指令集其实是不一样的,并不是说OpenQASM里面的所有指令都会 ...

  8. Laravel - Eloquent 删除数据

        public function ormDelete()     {         # 1.通过模型删除         // $student = Student::where('id',5 ...

  9. 百度网盘(百度云)SVIP超级会员共享账号每日更新(2023.12.18)

    一.百度网盘SVIP超级会员共享账号 可能很多人不懂这个共享账号是什么意思,小编在这里给大家做一下解答. 我们多知道百度网盘很大的用处就是类似U盘,不同的人把文件上传到百度网盘,别人可以直接下载,避免 ...

  10. [转帖]十步解析awr报告

    http://www.zhaibibei.cn/awr/1.1/ 从这期开始讲解awr报告的部分,首先讲解awr整体的部分 后续会针对不同的点进行讲解 1. 数据库细节 这部分可以看到 数据库的版本 ...