[Redis]扩容

news/2024/10/5 15:19:20/文章来源:https://www.cnblogs.com/DCFV/p/18288042

原因

扩容原因:当hashtable存储的元素过多,可能由于碰撞也过多,导致其中某链表很长,最后致使查找和插入时间复杂度很大。因此当元素超多一定的时候就需要扩容。
缩容原因:当元素数量比较少的时候就需要缩容以节约不必要的内存。为了让哈希表的负载因子(load factor)维持在一个合理的范围内,会使用rehash(重新散列)操作对哈希表进行相应的扩展或收缩。

负载因子的计算公式:哈希表已保存节点数量 / 哈希表大小
== load_factor = ht[0].used / ht[0].size ==

扩容条件(满足任意一个即可)

  • Redis服务器目前没有在执行BGSAVE或BGREWRITEAOF命令,并且哈希表的负载因子大于等于1。
  • Redis服务器目前在执行BGSAVE或BGREWRITEAOF命令,并且哈希表的负载因子大于等于5。

为什么BGSAVE或BGREWRITEAOF命令是否在执行,Redis服务器哈希表执行扩容所需的负载因子不相同(1或5)?

BGSAVE:用于在后台异步保存当前数据库的数据到磁盘。
BGREWRITEAOF:用于异步执行一个 AOF( Append Only File ) 文件重写操作。
因为当执行BGSAVE或BGREWRITEAOF命令过程中,Redis需要创建服务器进程的子进程,操作系统采用的是COW,即 写时复制 copy-on-write的技术来优化子进程的使用效率。所以在子进程存在时,服务器会提高执行扩容所需的负载因子,从而尽可能避免在子进程存在期间进行扩容,可以避免不必要的内存写入操作,最大限度节约内存。

PS:COW

“写时复制”(Copy-On-Write,简称 COW)是一种用于资源管理和优化的技术,主要应用在内存管理和系统设计中。它的基本思想是:如果有多个进程或线程需要读取同一个资源(如内存块或数据结构),它们可以共享该资源的单一副本;但是,当其中任何一个进程或线程尝试修改资源时,系统会为其创建一个资源的独立副本,这样可以确保其他进程或线程看到的仍然是原始未修改的资源。

应用场景

  1. 内存管理

    • 操作系统中的进程创建

      • 当操作系统使用 fork() 系统调用创建一个新的进程时,新的进程通常是父进程的一个副本。为了节省内存和提高效率,子进程会共享父进程的内存空间。在这种情况下,COW 技术允许子进程和父进程在读操作时共享同一块内存,只有当某个进程尝试写入内存时,才会为该进程创建内存的副本。
    • 虚拟内存管理

      • 在操作系统的虚拟内存管理中,COW 可以用于延迟分配物理内存。初始时,所有进程共享同一块物理内存,当有进程尝试写操作时,操作系统才分配新的物理内存页。
  2. 数据结构和算法

    • 在某些数据结构(如字符串、数组、列表等)中,COW 可以用来优化修改操作。对于不可变的数据结构或在多线程环境中,COW 能够提供一种安全且高效的方法来处理修改操作。

工作原理

以下是 COW 的基本工作原理:

  1. 初始状态:多个进程或线程共享同一个资源(如内存块)。此时,资源的引用计数器可能为多个。
  2. 读操作:所有进程或线程可以自由地读取共享的资源,而不需要创建副本。
  3. 写操作:当某个进程或线程需要修改资源时,系统会执行以下步骤:
    • 检查资源的引用计数器。如果引用计数器大于1,意味着资源被多个进程或线程共享。
    • 创建资源的一个独立副本,仅供当前进行写操作的进程或线程使用。
    • 将引用计数器减1。
  4. 更新引用:修改后的副本成为当前进程或线程的资源,其他进程或线程仍然引用原始资源。

优缺点

优点

  • 节省内存:多个进程或线程共享资源时,只需要存储一份资源副本,直到需要写操作时才创建副本。
  • 提高性能:减少不必要的资源复制操作,提高了系统的整体性能。

缺点

  • 写操作开销:首次写操作需要进行复制操作,这会引入额外的内存和时间开销。
  • 复杂性增加:实现 COW 机制需要更复杂的内存管理逻辑,增加了系统的复杂性。

示例

以下是一个简单的示例,演示 COW 在内存管理中的应用:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>int main() {pid_t pid;int *shared_memory = malloc(sizeof(int));*shared_memory = 42;printf("Original value: %d\n", *shared_memory);pid = fork();if (pid < 0) {perror("fork failed");exit(1);} else if (pid == 0) {// Child process*shared_memory = 100; // This triggers COWprintf("Child process value: %d\n", *shared_memory);exit(0);} else {// Parent processwait(NULL); // Wait for child process to finishprintf("Parent process value: %d\n", *shared_memory);}free(shared_memory);return 0;
}

在这个示例中,父进程和子进程在 fork() 后最初共享同一个 shared_memory 指针。当子进程尝试修改 shared_memory 的值时,系统会为子进程创建一个独立的副本,而父进程仍然保持对原始值的访问。

缩容条件

哈希表的负载因子小于0.1。

对字典的哈希表rehash步骤
为ht[1]分配空间:扩展操作,那么ht[1] 的大小为第一个大于等于ht[0] .used*2的2的n次幂;收缩操作,那么ht[1] 的大小为第一个大于等于ht[0].used 的2的n次幂
将ht[0]中的数据转移到ht[1]中,在转移的过程中,重新计算键的哈希值和索引值,然后将键值对放置到ht[1]的指定位置。
当ht[0]的所有键值对都迁移到了ht[1]之后(ht[0]变为空表),将ht[0]释放,然后将ht[1]设置成ht[0],最后为ht[1]分配一个空白哈希表:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/739573.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux系列】Linux 性能调优工具的 9 张图

性能观察工具静态性能工具性能压测工具性能调优工具sarperf-tools追踪工具BPF性能工具

「杂文」算法竞赛之黑话大赏

欢迎投稿。写在前面 欢迎投稿。 罚时 一种根据选手完成题目的耗时,用于对通过题目数量相同的选手,进行排名的指标。 仅有选手成功通过的题目,才会计算罚时。 一道成功通过的题目的罚时为:选手第一次通过该题目时间,距离比赛开始时间之差,再加上未成功提交的罚时惩罚。 选…

汇编语言 5. [BX] 和 loop | 实验 4 : [BX] 和 loop 的使用

1) 2)向内存 0:200 - 0:23F (0020:0 ~ 0020:3f) 依次传递数据 0~63 , 只用9个指令 使用 bx 即用于偏移地址[bx] 也用于普通寄存器 bx assume cs:codecode segmentmov ax,0020hmov ds,ax ; ds : 0020h mov cx,64mov bx, 0s: mov [bx],bxinc bxloop s mov ax,4c00hint …

WAF 大全

WAF 大全 宝塔网站防火墙

替换背景 工具

https://modelscope.cn/studios/iic/ReplaceAnything?spm=a2c6h.13066369.question.1.57fb7d45DCg601ReplaceAnything as you want: Ultra-high quality content replacement我们发现,在严格保持某个“物体ID”不变的情况下生成新的内容有着很大的市场需求,同时也是具有挑战…

算法入门(4) 7.6

[NOIP2008 普及组] ISBN 号码 题目描述 每一本正式出版的图书都有一个 ISBN 号码与之对应,ISBN 码包括 $9$ 位数字、$1$ 位识别码和 $3$ 位分隔符,其规定格式如 x-xxx-xxxxx-x,其中符号 - 就是分隔符(键盘上的减号),最后一位是识别码,例如 0-670-82162-4就是一个标准的 …

安装Nexus3和使用Nexus3搭建私有docker镜像仓库

1、官网下载Nexus3: https://help.sonatype.com/en/download.html 2、上传到服务器后解压:tar -xf nexus-3.69.0-02-java8-unix.tar.gz3、修改运行nexus配置 【1】修运行nexus所使用的用户:vim /opt/nexus3/nexus-3.69.0-02/binexus.rc #修改默认登陆用户为admin #run_as_us…

(9)逻辑综合添加约束(时序、DRC)

一、前言dc综合是一个不断迭代的过程,如果设计的RTL代码不满足时序约束的需求,则需要重新进行修改,然后再去综合,一直迭代到时序满足需求。 二、面积约束面积约束指令:set_max_area 100面积约束的定义有三种,一种指的是两输入与非门的个数,一种是晶体管的个数,第三种是…

深度解析 Raft 分布式一致性协议

深度解析 Raft 分布式一致性协议本文参考转载至:浅谈 Raft 分布式一致性协议|图解 Raft - 白泽来了 - 博客园 (cnblogs.com) 深度解析 Raft 分布式一致性协议 - 掘金 (juejin.cn) raft-zh_cn/raft-zh_cn.md at master maemual/raft-zh_cn (github.com)本篇文章将模拟一个KV数…

nacos学习笔记之服务发现中心

一.什么是服务发现 在微服务中,服务的消费方需要调用服务的生产方,这样服务的消费方就需要知道服务的消费方的网络地址(ip+端口号)。 二、流程上图中服务实例本身并不记录服务生产方的网络地址,所有服务实例内部都会包含服务发现客户端(例如spring cloud中的ribbon)。 (…

第一次学习Java的碎碎念

2024年夏新的学习开始了; 今天做了什么? 在B站上收藏了黑马程序员学习Java的教学视频,观看了几篇入门教程,暂时学会了如何打开CMD,以及几个常见的CMD命令,例如盘符名称:、dir、cd目录、cd..、cls、exit等等,做了一个练习(利用cmd打开qq),学会了如何把应用程序的路径…

测试标题

测试摘要\[a /ge b /eq c \]