Redis有哪些潜在的慢操作?
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有哪些潜在的慢操作?的更多相关文章
- Redis:安装、配置、操作和简单代码实例(C语言Client端)
Redis:安装.配置.操作和简单代码实例(C语言Client端) - hj19870806的专栏 - 博客频道 - CSDN.NET Redis:安装.配置.操作和简单代码实例(C语言Client端 ...
- redis对sorted_set进行的相关操作
redis对sorted_set(有序集合)类型操作的相关命令以及如何在python使用这些命令 redis对sorted_set(有序集合)类型操作的命令: 命令 语法 概述 返回值 Redis Z ...
- Redis 安装,配置以及数据操作
Nosql介绍 Nosql:一类新出现的数据库(not only sql)的特点 不支持SQL语法 存储结构跟传统关系型数据库中那种关系表完全不同,nosql中存储的数据都是k-v形式 Nosql的世 ...
- redis基础之基本键值操作和使用(三)
前言 redis安装完毕后开始使用redis,先熟悉命令行操作. redis数据的类型 键:redis的所有的键都是string类型: 值:五种类型 string:字符串类型:一个string最大可以 ...
- redis的String类型以及其操作
Redis的数据类型 String类型以及操作 String是最简单的数据类型,一个key对应一个Value,String类型是二进制安全的.Redis的String可以包含任何数据,比如jpg图片或 ...
- 在centos7中安装redis,并通过node.js操作redis
引言 最近在学习node.js 连接redis的模块,所以尝试了一下在虚拟机中安装cent OS7,并安装redis,并使用node.js 操作redis.所以顺便做个笔记. 如有不对的地方,欢迎大家 ...
- Redis数据类型Strings、Lists常用操作指令
Redis数据类型Strings.Lists常用操作指令 Strings常用操作指令 GET.SET相关操作 # GET 获取键值对 127.0.0.1:6379> get name (nil) ...
- Redis数据类型:Hashes、Geo操作指令
Redis数据类型:Hashes.Geo操作指令 Hashes常用操作指令 Redis Hashes是一个键值对的映射表,最对能存储2^32-1(约40亿)个键值对. HSET HGET HSET:将 ...
- Redis的C++与JavaScript访问操作
上篇简单介绍了Redis及其安装部署,这篇记录一下如何用C++语言和JavaScript语言访问操作Redis 1. Redis的接口访问方式(通用接口或者语言接口) 很多语言都包含Redis支持,R ...
- redis常用的命令行以及操作
redis常用的命令行以及操作 转载酱紫人的理直气壮 最后发布于2018-07-30 17:00:41 阅读数 805 收藏 转载地址:https://blog.csdn.net/li_lening ...
随机推荐
- 与奥运同行:打造智慧体育馆 3D 可视化
祝贺中国队在东京奥运会夺得金牌 38 枚.银牌 32 枚.铜牌 18 枚.中国健儿在奥运舞台上交出了一份璀璨的成绩单.用一场场精彩绝伦的比赛,演绎"更快.更高.更强.更团结"的奥林 ...
- vue3组件el-dialog提取
父组件: 1 <template> 2 <div class="auto-wrap"> 3 <div class="content-left ...
- jQuery组织后续事件 事件冒泡 事件委托 键被按下 批量操作 hover input 事件
1. jQuery绑定事件的方式 1. $('').click(function(){}) 2. $('').on('click', function(){}) 2. 阻止后续事件执行 1. retu ...
- ASIC 功能验证SVTB
System Verilog进行验证是可以不综合的 发现DUT中的功能问题 预备知识:Linux/verilog/gvim System Verilog学习目录 System Verilog Test ...
- 2. 成功使用SQL Plus完成连接,但在使用Oracle SQL Developer连接时,发生报错ORA-12526: TNS:listener: all appropriate instances are in restricted mode
经了解后得知,错误原因:ORA-12526: TNS: 监听程序: 所有适用例程都处于受限模式. 解决办法:使用系统管理员身份运行以下一段代码 ALTER SYSTEM DISABLE RESTRIC ...
- 【Printf】CubeMX生成MDK工程实现printf功能注意点
重定向printf int fputc(int ch, FILE *f) { /* Write a character to the USART */ USART1->DR = ch; /* L ...
- CSS : div 高度为0的三种情况
1, css 样式没正确绑定 ( 也就是没有设置高度 ) 2, 子元素 浮动 ( float ) 3, 子元素 绝对定位 ( position : absolute )
- Laravel - 使用 DB facade 实现CURD
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades ...
- [转帖]Linux 内核的 4 大 IO 调度算法
https://cloud.tencent.com/developer/article/1615744 Linux 内核包含4个IO调度器,分别是 Noop IO scheduler.Anticipa ...
- [转帖]谈谈ClickHouse性能情况以及相关优化
https://zhuanlan.zhihu.com/p/349105024 ClickHouse性能情况 主要分为4个方面 1.单个查询吞吐量 场景一: 如果数据被放置在page cache中,则一 ...