你不知道的Redis数据结构
你不知道的Redis数据结构
Redis数据结构
Redis作为缓存利器,不论是在工作中还是面试中都是需要对其足够了解,那么请你说出Redis的数据结构,你是否了解呢?相信一定有人脱口而出,String、List、Hash、Set、Sorted Set,这里一定一定要注意,问题指的是数据结构而不是数据类型,数据结构是数据类型的底层实现,应该为简单动态字符串、双向链表、压缩列表、哈希表、跳表、整型数组,数据类型和数据结构的关系如下。
了解完这些,我们就知道了Redis键值中的值保存形式,那么Redis的整体结构应该是什么样子呢
Redis的整体结构
Redis为实现快速存储,采用哈希表保存所有的键值对,哈希表本质就是数组,数组的每一个元素称为哈希桶,哈希桶中可以包含多个键值对,所以哈希表由多个哈希桶构成,这里需要注意的是键值对中的value在哈希桶中保存的只是指针,并不是字符串对象或者集合对象,整体结构如下所示
Redis的底层结构决定了所有的键查找时间复杂度都是O(1),因为Redis只需要计算键的哈希值就能得到键对应的数组下标从而得到哈希桶entry对象,从而访问value值,但是也就是因为这一特点衍生了另外一个问题。
哈希冲突
哈希冲突,全局哈希表长度有限那么不同键的哈希值完全有可能相同,也就是说不同键定位到的数组下标可能是同一个,这时就需要借鉴entry对象的next指针(这个可以参考JDK1.7HashMap的底层实现),采用哈希冲突链解决哈希冲突。
哈希冲突解决完毕是不是高枕无忧了呢?必然不是,采用哈希冲突链是能解决哈希冲突的问题,同时也带来了另外一个性能问题,哈希冲突链的访问只能是一个一个往下查找,如果冲突链过长查找效率自然变差,那么只要想办法将冲突链变短是不是就可以解决这个问题,所以Redis提出了Rehash的操作,就是增大哈希桶的数据,让集中存放在哈希桶中的entry对象,分散保存,减少每一个哈希桶的entry对象数(将哈希冲突链变短)从而减少哈希冲突。
Redis的Rehash操作
Redis默认使用两个全局哈希表,哈希表1和哈希表2,其中默认存储的是哈希表1,当哈希表1达到执行Rehash操作时,Redis会执行三个操作:
将哈希表2的容量初始化为哈希表1的两倍。
将哈希表1的值慢慢转移到哈希表2中。
释放哈希表1的空间。
至此Redis就完成了一次rehash,新的数据保存操作会在哈希表2中进行,后面如再需要Rehash时会利用哈希表1进行扩容,完成上述的三个步骤。如果有了解JVM的同学肯定马上想到这种替换操作和幸存0区和幸存1区的作用及其类似。
这里需要注意一个问题,Rehash的步骤2将哈希表1的值转移到哈希表2并不是一次性完成,而是多次执行,称为渐进式rehash,因为哈希表数据量大可能导致Redis线程阻塞,影响业务正常请求。
如图有如下初始数据,假设存在查询请求。
当请求1查询key1的值时其键值下标对应的是哈希表数组下标为1的位置,那么会先遍历数组下标为1的哈希冲突链,得到value值并返回,后面会将哈希冲突链的值从哈希表1转移到哈希表2上(会重新计算哈希)。
当请求2查询key2的值时其键值下标为2同样会执行返回value值的操作同时拷贝值到哈希表2上。
这样的机制就能将一次性大批量的拷贝操作,分摊到多次请求中来完成,避免耗时访问,提升访问效率。
注意点
在进行渐进式rehash时,其实对于哈希表的修改、删除、查询等操作都会在哈希表1和哈希表2中进行,例如查询操作在哈希表1中没有查询到数据就会去哈希表2中查询,其余类似,另外在渐进式哈希执行期间新增操作应该是保存到扩容的哈希表中(上图就是哈希表2,但不是一直都是哈希表2可能多次哈希),这样就能保证被扩容的哈希表(上图指哈希表1)只减不增,随着rehash的进行最后被扩容的哈希表变为空。
哈希表会在每一次请求的时候会将被扩容的哈希表1中数据拷贝到扩容哈希表2中,但如果一个数组下标的值从未有过请求去访问,那么是不是这个哈希表就永远无法完成复制呢?其实并不然就算没有请求去访问一个数组下标,同样会有定时任务去做数组拷贝,这样保证了访问量少的数据同样能复制到新的哈希表中。
你不知道的Redis数据结构相关推荐
- Redis 数据结构-字典源码分析
2019独角兽企业重金招聘Python工程师标准>>> 相关文章 Redis 初探-安装与使用 Redis 数据结构-字符串源码分析 本文将从以下几个方面介绍 前言 字典结构图 字典 ...
- 为了拿捏 Redis 数据结构,我画了 40 张图
Redis 为什么那么快? 除了它是内存数据库,使得所有的操作都在内存上进行之外,还有一个重要因素,它实现的数据结构,使得我们对数据进行增删查改操作时,Redis 能高效的处理. 因此,这次我们就来好 ...
- 【带你重拾Redis】Redis数据结构及使用场景
Redis数据结构 Redis有着非常丰富的数据结构,这些数据结构可以满足非常多的应用场景, 如果对这些数据结构有一个比较清晰的认知,使用Redis也会更加得心应手. Redis主要支持以下数据结构: ...
- 深入剖析Redis系列(七) - Redis数据结构之列表
前言 列表(list)类型是用来存储多个 有序 的 字符串.在 Redis 中,可以对列表的 两端 进行 插入(push)和 弹出(pop)操作,还可以获取 指定范围 的 元素列表.获取 指定索引下标 ...
- redis 自减命令_Redis 实战 —— 04. Redis 数据结构常用命令简介
字符串 P39 Redis 的字符串是一个有字节组成的序列,可以存储以下 3 种类型的值:字节串(byte string).整数.浮点数. 在需要的时候, Redis 会将整数转换成浮点数.整数的取值 ...
- redis数据结构详解之Hash(四)
原文:redis数据结构详解之Hash(四) 序言 Hash数据结构累似c#中的dictionary,大家对数组应该比较了解,数组是通过索引快速定位到指定元素的,无论是访问数组的第一个元素还是最后一个 ...
- zincrby redis python_【Redis数据结构 序】使用redispy操作Redis数据库
点击蓝色"不太灵光的程序员"关注我哟加个"星标",每天上午 08:00,干货推送!本文依旧会对学习内容进行拆分,建议阅读时间基本保持10分钟内,想学习之前章节内 ...
- redis 数据结构
2019独角兽企业重金招聘Python工程师标准>>> redis对象 redis 数据结构 字符串对象 SDS(简单动态字符串) 列表对象 压缩列表(ziplist) 或 链表 ...
- Redis 数据结构与内存管理策略(上)
Redis 数据结构与内存管理策略(上) 标签: Redis Redis数据结构 Redis内存管理策略 Redis数据类型 Redis类型映射 Redis 数据类型特点与使用场景 String.Li ...
最新文章
- javaScript小问题,托拽元素,获得当前鼠标的坐标
- 你可能已经知道或者不知道的ASP.NET 2.0技巧(转载)
- 测试 Zoundry Raven
- 设置elf文件链接库的路径
- ubuntu下搭建一个数据化处理的开发环境
- SpringBatch适配器详解
- 华为p7刷android go,华为首款Android GO手机发布 1G内存也流畅
- Stanford机器学习---第六讲. 怎样选择机器学习方法、系统
- 有什么软件可以测试win10电脑性能,微软能否翻盘 Win10系统4K高分优化实测
- Django框架orm
- Axure RP 9免费下载
- html表格动态添加图片,引用 制作html帖第四课:在表格中添加图片代码制作精美边框...
- 仓储管理之盘点——SAP盘点方法与流程
- 深度学习算法(第37期)----如何用强化学习玩游戏?
- java防止重复提交
- python小游戏之外星人入侵之pygame实战应用(含源码下载)
- JVM-详解G1垃圾收集器
- 如何应用卫星图像到Auto CAD
- 脱裤子放屁之用两个栈实现队列、用两个队列实现栈
- SHOGUN toolbox的一些使用心得
热门文章
- Extremely hard RSA 低加密指数攻击
- R语言基于库克距离统计量识别(Cook’s distance)对于回归模型性能或者预测影响(Influential observation)很大的观测样本、可视化库克距离并添加阈值线识别影响力大的样本
- StarUML3.0 的破解方法
- 基于电力大数据的空气污染预测
- 什么是代理ip,代理ip的用途有哪些?
- 《云计算服务安全能力要求》与《云计算服务安全指南》标准
- 网络安全-网站后台的寻找+网页JS文件信息收集
- k近邻算法_图穷匕见:K近邻算法与手写数字识别
- kerberos搭建
- Numerical Optimization和Convex optimization 两本书的选择?