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

Redis核心数据结构之字典(二)

字典

解决键冲突

当有两个或以上数量的键被分配到了一个哈希表数组的同一个索引上面,我们称这些键发生了冲突(collision)。
Redis的哈希表使用链地址法(separate chaining)来解决键冲突,每个哈希表节点都有一个next指针,多个哈希表节点可以用next指针构成一个单向链表,被分配到同一个索引上的多个节点可以用这个单向链表连接起来,这就解决了键冲突的问题。

例子

  • 举个例子,假设程序要将键值对K2和V2添加到图中的哈希表中,
    并且计算得出K2的索引值为2,那么K1和K2将产生冲突,而解决
    冲突的办法就是使用next指针将键K2和K1所在的节点连接起来
    在这里插入图片描述
  • 因为dictEntry节点组成的链表没有指向链表表尾的指针,所以为了
    速度考虑,程序总是将新节点添加到链表的表头位置(复杂度为O(1)),
    排在其他已有节点的前面
    在这里插入图片描述

rehash

随着操作的不断执行,哈希表保存的键值对会逐渐地增多或者减少,为了让哈希表的负载因子(load factor)维持在一个合理的范围之内,当哈希表保存的键值对数量太多或者太少时,程序需要对哈希表的大小进行相应的扩展或者收缩。扩展和收缩哈希表的工作可以通过执行rehash(重新散列)操作来完成,Redis对字典的哈希表执行rehash的步骤如下:

  • 1.为字典的ht[1]哈希表分配空间,这个哈希表的空间大小取决于要执行的操作,以及ht[0]当前包含的键值对数量(也即是ht[0].used属性的值):
  • 1.1 如果执行的是扩展操纵,那么ht[1]的大小为第一个大于等于ht[0].used * 2的2 ^ n(2的n次幂)
  • 1.2 如果执行的收缩操作,那么ht[1]的大小为第一个大于等于ht[0].used的2^n
  • 2.将保存在ht[0]中的所有键值对rehash到ht[1]上面:rehash指的是重新计算键的哈希值和索引值,然后将键值对放置到ht[1]哈希表的指定位置上。
  • 3.当ht[0]包含的所有键值对都迁移到了ht[1]之后(ht[0]变为空表),释放ht[0],将ht[1]设置为ht[0],并在ht[1]新创建一个空白哈希表,为下一次rehash做准备。

例子

  • 举个例子,假设程序要对图中字典的ht[0]进行扩展操作,
    程序将执行如下步骤
    在这里插入图片描述
    1.ht[0].used当前的值为4,4 * 2 = 8,而8(2^3)恰好是第一个大于等于4的2的n次方,所以程序会将ht[1]哈希表的大小设置为8.
    在这里插入图片描述
    2.将ht[0]包含的四个键值对都rehas到ht[1],如图所示
    在这里插入图片描述
    3.释放ht[0],并将ht[1]设置为ht[0],然后为ht[1]分配一个空白哈希表,如图所示。至此,对哈希表的扩展操作执行完毕,程序成功将哈希表的大小从原来的4改为了现在的8
    在这里插入图片描述

哈希表的扩展与收缩

当以下条件中的任意一个被满足时,程序会自动开始对哈希表执行扩展操作:

  • 1.服务器目前没有在执行BGSAVE命令或者BGREWRITEAOF命令,并且哈希表的负载因子大于等于1
  • 2.服务器目前正在执行BGSAVE命令或者BGREWRITEAOF命令,并且哈希表的负载因子大于等于5
    其中哈希表的负载因子可以通过公式:
    #负载因子 = 哈希表已保存节点数量 / 哈希表大小
    load_factor = ht[0].used / ht[0].size

根据BGSAVE命令或BGREWRITEAOF命令是否正在执行,服务器执行扩展操作所需的负载因子并不相同,这是因为在执行BGSAVE命令或BGREWRITEAOF命令的过程中,Redis需要创建当前服务器进程
的子进程,而大多数操作系统都采用写时复制(copy-on-write)技术来优化子进程的使用效率,所以在子进程存在期间,服务器会提高执行扩展操作所需的负载因子,从而尽可能地避免在子进程存在期间进行哈希表扩展操作,这可以避免不必要地内存写入操作,最大限度地节约内存。
另一方面,当哈希表地负载因子小于0.1时,程序自动开始对哈希表执行收缩操作

例子

  • 例如,对于一个大小为4,包含4个键值对的哈希表来说,这个哈希表的负载因子为load_factor = 4 / 4 = 1;
  • 例如,对于一个大小为512,包含256个键值对的哈希表来说,这个哈希表的负载因子是:load_factor = 256 / 512 = 0.5

渐进式rehash

扩展或收缩哈希表需要将ht[0]里面的所有键值对rehash到ht[1]里面,但是,这个rehash动作并不是一次性、集中式地完成,而是分多次、渐进式地完成的。这样做的原因在于,如果ht[0]里只保存着四个键值对,那么
服务器可以在瞬间就将这些键值对全部rehash到ht[1];但是,如果哈希表里保存的键值对数量不是四个,而是四百万、四千万甚至四亿个键值对,那么要一次性将这些键值对全部rehash到ht[1]的话,庞大的计算量
可能会导致服务器在一段时间内停止服务。因此为了避免rehash对服务器性能造成影响,服务器不是一次性将ht[0]里面地所有键值对全部rehash到ht[1],而是分多次、渐进式地将ht[0]里面地键值对慢慢地rehash到ht[1]

哈希表渐进式rehash的详细步骤:

  • 1.为ht[1]分配空间,让字典同时持有ht[0]和ht[1]两个哈希表

  • 2.在字典中维持一个索引计数器变量rehashidx,并将它的值设置为0,表示rehash工作正式开始

  • 3.在rehash进行期间,每次对字典执行添加、删除、查找或者更新操作时,程序除了执行指定的操作以外,还会顺带将ht[0]哈希表在rehashidx索引上的所有键值对rehash到ht[1],当rehash工作完成之后,程序将
    rehashidx属性的值增一

  • 4.随着字典操作的不断执行,最终在某个时间点上,ht[0]的所有键值对都会被rehash至ht[1],这时程序将rehashidx属性的至设为-1,表示rehash操作已完成。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 渐进式rehash的好处在于它采取分而治之的方式,将rehash键值对所需的计算工作均摊到对每个添加、删除、查找、
    更新操作上,从而避免了集中式rehash而带来的庞大计算量

  • 渐进式rehash执行期间的哈希表操作因为在进行渐进式rehash的过程中,字典会同时使用ht[0]和ht[1]两个哈希表,所以在渐进式rehash进行期间,字典的删除、查找、更新等操作会在两个哈希表上进行。例如,要在字典里面查找一个键的话,程序会在ht[0]里面进行查找,如果没有找到的话,就会继续到ht[1]里面进行查找,诸如此类。另外,在渐进式rehash执行操作期间,新添加到的字典的键值对一律会被保存到ht[1]里面,而ht[0]则不再进行任何添加操作,这一措施保证了ht[0]包含的键值对数量会只减不增,并随着rehash操作的执行而最终变成空表

相关文章:

Redis核心数据结构之字典(二)

字典 解决键冲突 当有两个或以上数量的键被分配到了一个哈希表数组的同一个索引上面,我们称这些键发生了冲突(collision)。 Redis的哈希表使用链地址法(separate chaining)来解决键冲突,每个哈希表节点都有一个next指针,多个哈希表节点可以…...

拯救行动(BFS)

公主被恶人抓走,被关押在牢房的某个地方。牢房用 N \times M (N, M \le 200)NM(N,M≤200) 的矩阵来表示。矩阵中的每项可以代表道路()、墙壁(#)、和守卫(x)。 英勇的骑士(r&#xf…...

985硕的4家大厂实习与校招经历专题分享(part2)

我的个人经历: 985硕士24届毕业生,实验室方向:CV深度学习 就业:工程-java后端 关注大模型相关技术发展 校招offer: 阿里巴巴 字节跳动 等10 研究生期间独立发了一篇二区SCI 实习经历:字节 阿里 京东 B站 (只看大厂,面试…...

【NR技术】 3GPP支持无人机的关键技术以及场景

1 背景 人们对使用蜂窝连接来支持无人机系统(UAS)的兴趣浓厚,3GPP生态系统为UAS的运行提供了极好的好处。无处不在的覆盖范围、高可靠性和QoS、强大的安全性和无缝移动性是支持UAS指挥和控制功能的关键因素。与此同时,监管机构正在调查安全和性能标准以及…...

【译】WordPress Bricks主题安全漏洞曝光,25,000个安装受影响

WordPress的Bricks主题存在一个严重的安全漏洞,恶意威胁行为者正在积极利用该漏洞在易受攻击的安装上运行任意PHP代码。 该漏洞被跟踪为CVE-2024-25600(CVSS评分:9.8),使未经身份验证的攻击者能够实现远程代码执行。它…...

【C++ 23种设计模式】

C 23种设计模式 ■ 创建型模式(5种)■ 工厂模式■ 抽象工厂模式■ 原型模式■ 单例模式■ 第一种:单线程(懒汉)■ 第二种:多线程(互斥量实现锁懒汉)■ 第三种:多线程(const static饿…...

亚信安慧AntDB:企业数据管理的明日之星

在信息科技飞速发展的时代,亚信科技AntDB团队提出了一项颠覆性的“超融合”理念,旨在满足企业日益增长的复杂混合负载和多样化数据类型的业务需求。这一创新性框架的核心思想在于融合多引擎和多能力,充分发挥分布式数据库引擎的架构优势&…...

Android Gradle开发与应用 (三) : Groovy语法概念与闭包

1. Groovy介绍 Groovy是一种基于Java平台的动态编程语言,与Java是完全兼容,除此之外有很多的语法糖来方便我们开发。Groovy代码能够直接运行在Java虚拟机(JVM)上,也可以被编译成Java字节码文件。 以下是Groovy的一些…...

Android 14 设置锁屏为NONE后开启双卡PIN锁,重启设备后,输完卡1的PIN码就进入了安卓界面,未提示输入卡2的PIN码

一.问题背景 目前在多个Android14平台发现开启双卡PIN码并且关闭屏幕锁的情况下,第二个PIN码锁输入弹框不能弹出问题,导致第二个卡不能注网。 如下是未修改前重启后解锁卡1PIN码的状态 可以看出卡2不能正常使用 二.何处关闭了卡2的PIN锁? 1.添加日志 首先在KeyguardSecu…...

2024 GoLand激活,分享几个GoLand激活的方案

文章目录 GoLand公司简介我这边使用GoLand的理由GoLand 最新变化GoLand 2023.3 最新变化AI Assistant 正式版GoLand 中的 AI Assistant:_Rename_(重命名)GoLand 中的 AI Assistant:_Write documentation_(编写文档&…...

linux中对信号的认识

信号的概念与相关知识认识 信号是向目标进程发送消息通知的的一种机制。 信号可以以异步的方式发送给进程,也就是说,进程无需主动等待,而是在任何时间都可以接收到信号。 信号的种类 用kill-l命令查看系统定义的信号列表: 前台…...

【万题详解】P1048 [NOIP2005 普及组] 采药

题目描述 链接——题目在这里!!! 辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草…...

Golang基于Redis bitmap实现布隆过滤器(完结版)

Golang基于Redis bitmap实现布隆过滤器(完结版) 为了防止黑客恶意刷接口(请求压根不存在的数据),目前通常有以下几种做法: 限制IP(限流)Redis缓存不存在的key布隆过滤器挡在Redis前 …...

Java基础-内部类

内部类 引言内部类的共性成员内部类静态内部类非静态内部类 局部内部类匿名内部类内部类的使用场景和好处 引言 Java不仅可以定义变量和方法,还可以定义类. 内部类允许你把一些逻辑相关的类组织在一起,并可以控制内部中类的可见性. 这么看来,内部类就像是代码一种隐藏机制:将类…...

设计模式-行为型模式-职责链模式

在软件系统运行时,对象并不是孤立存在的,它们可以通过相互通信协作完成某些功能,一个对象在运行时也将影响到其他对象的运行。行为型模式(Behavioral Pattern)关注系统中对象之间的交互,研究系统在运行时对…...

代码随想录算法训练营第四十天|LeetCode343 整数拆分、LeetCode96 不同的二叉搜索树

343.整数拆分 思路:确定dp数组以及下标的含义 dp[i]代表 i可以被拆分后的最大乘积。确定递推公式,假如拆成连个数,dp[i] j*(i-j),拆成两个数以上,dp[i]j*dp[i-j],j的范围为1到i-1.dp[i]找到所有情况的最大值。初始化…...

接口自动化测试用例如何设计

说到自动化测试,或者说接口自动化测试,多数人的第一反应是该用什么工具,比如:Python Requests、Java HttpClient、Apifox、MeterSphere、自研的自动化平台等。大家似乎更关注的是哪个工具更优秀,甚至出现“ 做平台的 &…...

弱电综合布线:连接现代生活的纽带

在当今信息化快速发展的时代,弱电网络布线作为信息传输的重要基础设施,其作用日益凸显。它不仅保障了数据的高效流通,还确保了通信的稳定性。从商业大厦到教育机构,从政府机关到医院急救中心,再到我们居住的社区&#…...

Java零基础 - 数组的定义和声明

哈喽,各位小伙伴们,你们好呀,我是喵手。 今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。 我是一名后…...

CSS补充(下),弹性布局(上)

高级选择器 1.兄弟选择器 2.同时满足 div.bg{background-color: red;}p.bg{background-color: green;}spam.bg{background-color: blue;}注:选择器中间没有空格,有明确标识的选择器写在后面 3.各种伪类的应用 3.1作为第几个子元素 选择器:nth-child…...

图数据库 之 Neo4j - 应用场景4 - 反洗钱(9)

原理 Neo4j图数据库可以用于构建和分析数据之间的关系。它使用节点和关系来表示数据,并提供实时查询能力。通过使用Neo4j,可以将大量的交易数据导入图数据库,并通过查询和分析图结构来发现洗钱行为中的模式和关联。 案例分析 假设有一家转账服务公司,有以下交易数据,每个…...

uboot分区介绍

RK平台的U-Boot支持两种分区表 RK paramter格式(旧)和 标准GPT格式(新),当机器上同时存在 两种分区表时,优先使用GPT分区表。无论是 GPT 还是 RK parameter,烧写用的分区表文件都叫parameter.t…...

快速收集诊断信息,敏捷诊断工具obdiag应用实践——《OceanBase诊断系列》之三

1. 前言 作为OceanBase的敏捷诊断工具,obdiag具有以下特点: 部署便捷:提供rpm包和OBD上部署的模式,都能够一键部署安装。用户可以选择将其部署到集群中任意一台能连接到各个节点的设备上,而不仅限于OBServer节点。即…...

C++错误总结(1)

1.定义函数类型时,如果没有返回值,用void void swap(int &x, int &y){ int tem x; x y; y tem; } 2.输入时,不加换行符 cin >> a >> b >> c >> endl ;(红色标记的是错误的部分) 3.【逆序出入…...

std::shared_from_this注意事项:exception bad_weak_ptr

1.不可以在构造函数中调用shared_from_this() 因为它的实现是&#xff1a; _LIBCPP_INLINE_VISIBILITYshared_ptr<_Tp> shared_from_this(){return shared_ptr<_Tp>(__weak_this_);}也就是它依赖的__weak_this_此时还未创建完成。 2.一定要public继承 class MyTy…...

【工具】Raycast – Mac提效工具

引入 以前看到同事们锁屏的时候&#xff0c;不知按了什么键&#xff0c;直接调出这个框&#xff0c;然后输入lock屏幕就锁了。 跟我习惯的按Mac开机键不大一样。个人觉得还是蛮炫酷的&#xff5e; 调研 但是由于之前比较繁忙&#xff0c;这件事其实都忘的差不多了&#xff0…...

蓝桥杯集训·每日一题2024 (二分,双指针)

前言&#xff1a; 开学了&#xff0c;平时学习的压力也逐渐大起来了&#xff0c;不过还算可以接受&#xff0c;等到后面阶段考的时候就不一样了&#xff0c;我目前为了转专业退选了很多课&#xff0c;这些课我都需要花时间来刷绩点&#xff0c;不然保研就没有竞争力了。我自己会…...

在Linux(Ubuntu)中使用终端编译 vscode安装

文章目录 &#x1f4da;在Linux&#xff08;Ubuntu&#xff09;中使用终端编译&#x1f407;.cpp程序编译&#x1f407;.py程序编译&#x1f407;查看Python、C编程环境 &#x1f4da;vscode安装 &#x1f4da;在Linux&#xff08;Ubuntu&#xff09;中使用终端编译 虚拟机安装…...

官网正在被哪些产品蚕食,定制网站又被哪些建站产品挤占。

2023-12-09 16:22贝格前端工场 官网建设是一个被大多数人看衰的市场&#xff0c;本文来理性分析下&#xff0c;谁在蚕食这个市场&#xff0c;谁又在挤占这个产品生存空间&#xff0c;欢迎大家评论&#xff0c;探讨。 网站正在被以下产品形式取代&#xff1a; 1. 移动应用&…...

BUUCTF---[MRCTF2020]你传你呢1

1.题目描述 2.打开题目链接 3.上传shell.jpg文件&#xff0c;显示连接成功&#xff0c;但是用蚁剑连接却连接不上。shell文件内容为 <script languagephp>eval($_REQUEST[cmd]);</script>4.用bp抓包&#xff0c;修改属性 5.需要上传一个.htaccess的文件来把jpg后缀…...