你不知道的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数据结构相关推荐

  1. Redis 数据结构-字典源码分析

    2019独角兽企业重金招聘Python工程师标准>>> 相关文章 Redis 初探-安装与使用 Redis 数据结构-字符串源码分析 本文将从以下几个方面介绍 前言 字典结构图 字典 ...

  2. 为了拿捏 Redis 数据结构,我画了 40 张图

    Redis 为什么那么快? 除了它是内存数据库,使得所有的操作都在内存上进行之外,还有一个重要因素,它实现的数据结构,使得我们对数据进行增删查改操作时,Redis 能高效的处理. 因此,这次我们就来好 ...

  3. 【带你重拾Redis】Redis数据结构及使用场景

    Redis数据结构 Redis有着非常丰富的数据结构,这些数据结构可以满足非常多的应用场景, 如果对这些数据结构有一个比较清晰的认知,使用Redis也会更加得心应手. Redis主要支持以下数据结构: ...

  4. 深入剖析Redis系列(七) - Redis数据结构之列表

    前言 列表(list)类型是用来存储多个 有序 的 字符串.在 Redis 中,可以对列表的 两端 进行 插入(push)和 弹出(pop)操作,还可以获取 指定范围 的 元素列表.获取 指定索引下标 ...

  5. redis 自减命令_Redis 实战 —— 04. Redis 数据结构常用命令简介

    字符串 P39 Redis 的字符串是一个有字节组成的序列,可以存储以下 3 种类型的值:字节串(byte string).整数.浮点数. 在需要的时候, Redis 会将整数转换成浮点数.整数的取值 ...

  6. redis数据结构详解之Hash(四)

    原文:redis数据结构详解之Hash(四) 序言 Hash数据结构累似c#中的dictionary,大家对数组应该比较了解,数组是通过索引快速定位到指定元素的,无论是访问数组的第一个元素还是最后一个 ...

  7. zincrby redis python_【Redis数据结构 序】使用redispy操作Redis数据库

    点击蓝色"不太灵光的程序员"关注我哟加个"星标",每天上午 08:00,干货推送!本文依旧会对学习内容进行拆分,建议阅读时间基本保持10分钟内,想学习之前章节内 ...

  8. redis 数据结构

    2019独角兽企业重金招聘Python工程师标准>>> redis对象 redis 数据结构 字符串对象  SDS(简单动态字符串) 列表对象  压缩列表(ziplist) 或 链表 ...

  9. Redis 数据结构与内存管理策略(上)

    Redis 数据结构与内存管理策略(上) 标签: Redis Redis数据结构 Redis内存管理策略 Redis数据类型 Redis类型映射 Redis 数据类型特点与使用场景 String.Li ...

最新文章

  1. javaScript小问题,托拽元素,获得当前鼠标的坐标
  2. 你可能已经知道或者不知道的ASP.NET 2.0技巧(转载)
  3. 测试 Zoundry Raven
  4. 设置elf文件链接库的路径
  5. ubuntu下搭建一个数据化处理的开发环境
  6. SpringBatch适配器详解
  7. 华为p7刷android go,华为首款Android GO手机发布 1G内存也流畅
  8. Stanford机器学习---第六讲. 怎样选择机器学习方法、系统
  9. 有什么软件可以测试win10电脑性能,微软能否翻盘 Win10系统4K高分优化实测
  10. Django框架orm
  11. Axure RP 9免费下载
  12. html表格动态添加图片,引用 制作html帖第四课:在表格中添加图片代码制作精美边框...
  13. 仓储管理之盘点——SAP盘点方法与流程
  14. 深度学习算法(第37期)----如何用强化学习玩游戏?
  15. java防止重复提交
  16. python小游戏之外星人入侵之pygame实战应用(含源码下载)
  17. JVM-详解G1垃圾收集器
  18. 如何应用卫星图像到Auto CAD
  19. 脱裤子放屁之用两个栈实现队列、用两个队列实现栈
  20. SHOGUN toolbox的一些使用心得

热门文章

  1. Extremely hard RSA 低加密指数攻击
  2. R语言基于库克距离统计量识别(Cook’s distance)对于回归模型性能或者预测影响(Influential observation)很大的观测样本、可视化库克距离并添加阈值线识别影响力大的样本
  3. StarUML3.0 的破解方法
  4. 基于电力大数据的空气污染预测
  5. 什么是代理ip,代理ip的用途有哪些?
  6. 《云计算服务安全能力要求》与《云计算服务安全指南》标准
  7. 网络安全-网站后台的寻找+网页JS文件信息收集
  8. k近邻算法_图穷匕见:K近邻算法与手写数字识别
  9. kerberos搭建
  10. Numerical Optimization和Convex optimization 两本书的选择?