当前位置: 首页 > news >正文

Redis是如何避免“数组+链表”的过长问题

目录

一、扩展和收缩

二、使用高质量的哈希函数

三、使用跳跃表(skiplist)或其他数据结构

四、哈希表分片


一、扩展和收缩

       Redis通过动态调整哈希表的大小来解决“数组+链表”的长度问题,这涉及到两个过程:扩展(Expand)和收缩(Shrink)。

  1. 扩展:

    • 当哈希表的负载因子(load factor)超过一个阈值时,Redis会进行扩展操作。
    • 负载因子是哈希表已存储的元素数量与哈希表大小的比值。
    • 扩展操作包括分配一个新的更大的哈希表,并逐渐将旧表中的所有键值对rehash到新表中。
  2. 收缩:

    • 相对地,当负载因子低于另一个阈值时,Redis会执行收缩操作,减少哈希表的大小。
    • 这通常发生在删除大量键值对后,为了节省内存空间,Redis会将键值对rehash到一个更小的哈希表中。

   负载因子和rehash

  • 负载因子的计算:

    • 负载因子 = 哈希表中的元素数量 / 哈希表的大小
    • 当负载因子太高时,意味着发生哈希冲突的可能性增加,链表会变得较长,影响性能。
    • 当负载因子太低时,意味着内存使用不够高效。
    • 默认扩展负载因子:
      • 在没有进行BGSAVE或BGREWRITEAOF操作时,负载因子超过1时进行扩展。
      • 如果正在进行BGSAVE或BGREWRITEAOF操作,则负载因子阈值提高到5,即负载因子超过5时进行扩展。这意味着在正常情况下,当哈希表的负载因子超过1时,Redis就会触发扩展操作。但是,如果Redis正在进行磁盘写操作,如BGSAVE或BGREWRITEAOF,为了避免在磁盘IO已经很高的情况下进一步增加内存重分配的负担,它会提高扩展操作的负载因子阈值到5。这样可以在一定程度上平衡内存使用和磁盘IO之间的性能。
    • 当哈希表的负载因子小于0.1时,Redis会进行收缩操作。
  • rehash过程:

    • rehash是将所有键值对从旧的哈希表移动到新的哈希表的过程。
    • Redis使用渐进式rehash,它不是一次性完成,而是分多次进行,以避免长时间的阻塞。

   渐进式rehash

  • 渐进式rehash的实现:
    • 在rehash期间,Redis同时保持旧表和新表。
    • 每次对哈希表的操作(如添加、删除、查找)时,Redis会将旧哈希表的一部分键值对迁移到新哈希表。
    • 这样可以将rehash的计算量分散到每个操作上,避免一次性的大量计算导致服务不可用。

二、使用高质量的哈希函数

       Redis使用MurmurHash等高质量的哈希函数来减少哈希冲突。

三、使用跳跃表(skiplist)或其他数据结构

     对于有序数据集合,Redis使用跳跃表而不是链表来存储元素,跳跃表的平均和最坏情况下的时间复杂度都比链表要好。

四、哈希表分片

  在Redis集群模式下,哈希表会被分成多个分片,每个分片由不同的Redis节点管理,这样可以分散负载,减少单个链表过长的风险。

相关文章:

  • React【Day1】
  • 【大模型】在VS Code(Visual Studio Code)上安装中文汉化版插件
  • [激光原理与应用-78]:激光加工(如打标)的各种笔参数与含义解读
  • MCGS学习——用户管理
  • XUbuntu22.04之安装Plantuml(二百二十三)
  • Camera入门基础知识
  • UGUI源码分析与研究2-从底层实现的角度去分析和调优UI的性能问题和疑难杂症
  • 加载三维模型,加载时黑的?
  • 前端视角如何理解“时间复杂度O(n)”
  • 【算法】小强爱数学(迭代公式+数论取模)
  • Unity学习笔记 6.2D换帧动画
  • Java后端八股----JVM篇
  • RuoYi-Vue-Plus(基础知识点jackson、mybatisplus、redis)
  • 十.pandas方法总结Numpy
  • 数据结构——双向链表(C语言版)
  • 【腾讯Bugly干货分享】从0到1打造直播 App
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • Bootstrap JS插件Alert源码分析
  • co模块的前端实现
  • CSS实用技巧干货
  • gf框架之分页模块(五) - 自定义分页
  • JS基础篇--通过JS生成由字母与数字组合的随机字符串
  • js写一个简单的选项卡
  • Python学习之路16-使用API
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 计算机常识 - 收藏集 - 掘金
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • 算法-插入排序
  • 微服务框架lagom
  • 学习ES6 变量的解构赋值
  • 一文看透浏览器架构
  • 以太坊客户端Geth命令参数详解
  • 译米田引理
  • 在Docker Swarm上部署Apache Storm:第1部分
  • 走向全栈之MongoDB的使用
  • 400多位云计算专家和开发者,加入了同一个组织 ...
  • 智能情侣枕Pillow Talk,倾听彼此的心跳
  • ​MPV,汽车产品里一个特殊品类的进化过程
  • ​业务双活的数据切换思路设计(下)
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • #pragma once与条件编译
  • $L^p$ 调和函数恒为零
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (牛客腾讯思维编程题)编码编码分组打印下标题目分析
  • (四)汇编语言——简单程序
  • (正则)提取页面里的img标签
  • *Algs4-1.5.25随机网格的倍率测试-(未读懂题)
  • .gitignore
  • .MyFile@waifu.club.wis.mkp勒索病毒数据怎么处理|数据解密恢复
  • .net core 6 集成和使用 mongodb
  • .NET CORE Aws S3 使用
  • .net core 微服务_.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端
  • .NET 应用启用与禁用自动生成绑定重定向 (bindingRedirect),解决不同版本 dll 的依赖问题