《Redis设计与实现》阅读总结-2

 第 7 章 压缩列表

1. 概念:

  • 压缩列表是列表键和哈希键的底层实现之一。
  • 当一个列表键只包含少量列表项,并且每个列表项是小整数值或长度比较短的字符串,那么Redis就会使用压缩类别来做列表键的底层实现。
  • 哈希键里面包含的所有键和值都是最小整数值或短字符串。

2. 压缩列表的构成:

  • 压缩列表是Redis为了节约内存而开发的,是由一系列特殊编码的连续内存块组成的书序结构。

3. 压缩列表节点的构成:

4. 连锁更新:

每个节点的previous_entry_length属性记录了前一个节点的长度:如果前一个字节长度小于254字节,那么previous_entry_length属性需要用1字节空间保存这个值,如果前一个字节的长度大于或等于254字节,那么previous_entry_length属性需要5字节的空间保存这个值。

如果在压缩列表中新添加一个长度大于等于254字节的节点,导致后边所有节点多次空间拓展的操作称为“连锁更新”。

5. 其他:

  • 压缩列表是一种为了节约内存而开发的顺序型数据结构。
  • 压缩列表可以包含多个节点,每个节点可以保存一个字节数组或整数值。
  • 添加节点或者删除节点可能或引发连锁更新操作,但是这种操作出现的几率不高。

第 8 章 对象

1. 概念:

  • Redis没有直接使用这些数据结构来实现键值对数据库,而是基于这些数据结构创建了一个对象系统。
  • 我们可以针对不同的使用场景,为对象设置不同的数据结构,从而优化对象在不同场景下的使用效率。
  • Redis对象系统基于引用计数计数的内存回收机制,可以有效节约内存。‘
  • Redis的对象带有访问时间记录信息,该信息可用用于计算数据库键的空转时间,在服务器启用了maxmemory功能的情况下,空转时长较大的那些键可能优先被服务器删除。

2. 对象类型:

3. 对象结构:

不同类型值对象的 Type命令的输出:

不同类型和编码的对象:

Object encoding对不同编码的输出:

 4. 各种对象的编码:

  • 字符串对象:

编码可以是int、raw或者embstr。

如果字符串对象保存的是整数值,并且这个整数值可以用long类型来表示,象编码设置为int。

如果字符串对象保存是一个字符串值,并且这个字符串的长度大于32字节,使用SDS保存这个字符串,并且对象编码设置为raw。

如果字符串对象保存是一个字符串值,并且这个字符串的长度小于等于32字节,使用SDS保存这个字符串,并且对象编码设置为embstr。

long double 类型表示的浮点数,是转换成字符串保存的,对象编码为embstr。

int编码字符串对象不是整数值时,会int->raw

embstr编码字符串对象执行任何修改时,会embstr->raw。

 

  • 列表对象:

编码可以是ziplist或者linkedlist。

满足所有字符串元素的长度都是小于64字节,并且保存元素数量小于512个时使用ziplist,否则使用linkedlist。

  • 哈希对象:

编码可以是ziplist或者hashtable。

满足所有字符串元素的长度都是小于64字节,并且保存元素键值对数量小于512个时使用ziplist,否则使用hashtable。

 

  • 集合对象:

编码可以是intset(整数集合)或者hashtable。

满足对象保存的所有元素都是整数值,并且保存对象的元素数量不超过512个使用intset,否则使用hashtable。

  • 有序集合对象:

编码可以是ziplist或者skiplist。

满足所有字符串元素的长度都是小于64字节,并且保存元素数量小于128个时使用ziplist,否则使用skiplist。

5. 内存回收:

        C语言并不具备内存回收功能,所以Redis在对象系统中构建了一个引用计数技术来实现内存回收机制。

6. 对象共享:

        对象的引用计数属性还带有对象共享的作用。

        Redis只对包含整数值的字符串对象进行共享,即共享值为0到9999的字符串对象。

7. 对象的空转时长:

        redisObject结果包含最后一个属性lru属性,该属性记录了对象最后一次被命令程序访问的时间。空转时长=当前时间-lru的值。

第 9 章 数据库

1. 读写键空间时的维护操作:

  • 在取读一个键之后(读操作和写操作都要对键进行取读),服务器会根据键是否存在来更新服务器的键空间命中(hit)次数或键空间不命中(miss)次数;
  • 在读取一个键之后,服务器会更新键的LRU(最后一次使用)时间,这个值可以用于计算键的闲置时间;
  • 如果服务器在读取一个键时发现该键已经过期,那么服务器会先刑除这个过期键,然后在执行余下其他操作;
  • 如果有客户端使用 WATCH命令监视了某个键,那么服务器在对被监视的键进行修改之后,会将这个键标记为脏( dirty),从而让事务程序注意到这个键已经被修改;
  • 服务器每次修改一个键之后,都会对脏( dirty)键计数器的值增1,这个计数器会触发服务器的持久化以及复制操作;
  • 如果服务器开启了数据库通知功能,那么在对键进行修改之后,服务器将按配置发送相应的数据库通知。

2. 过期键删除策略:

  • 定时删除:在设置键的过期时间的同时,创建一个定时器( timer),让定时器在键的过期时间来临时,立即执行对键的删除操作。
  • 惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检査取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。
  • 定期删除:每隔一段时间,程序就对数据库进行一次检査,删除里面的过期键。至于要删除多少过期键,以及要检査多少个数据库,则由算法决定。

        在这三种策略中,第一种和第三种为主动删除策略,而第二种则为被动刑除策略。

3. Redis的过期键删除策略:

        redis使用惰性删除和定期删除策略:通过配合使用这两种策略,服务器可以很好地合理使用CPU时间和避免浪费内存空间之间确定平衡。

4. AOF、RDB和复制功能对过期键的处理:

  • RDB

        生成RDB文件时(使用save或bgsave命令),不会将过期键存入RDB文件中;

        载入RDB文件时,如果服务器以主服务器运行,忽略过期键,如果服务器以从服务器运行,过期键会正常载入,但主从同步时候过期键会被清空。

  • AOF

        AOF写入时,如果键过期,但还没有被惰性删除或者定期删除,那么AOF文件不会因为这个过期键而产生影响,当过期键被惰性删除或者定期删除后,程序会向AOF文件追加一条DEL命令。

        AOF重写,过期的键不会被保存重写到AOF的文件中。

  • 复制

        当服务器运行在复制模式下时,从服务器的过期键删除动作是由主服务器控制:

        i. 主服务器在删除一个过期键之后,会显式地向所有从服务器发送一个DEL命令,告诉从服务器删除这个过期键。

        ii. 从服务器在执行客户端发送的读命令时,即使碰到过期键也不会将过期键删除,而是继续想处理未过期键一样处理过期键

        iii. 从服务器只有在接到主服务器发来的DEL命令之后,才会删除过期键。

5. 重点回顾:

  • Redis服务器的所有数据库都保存在 redisServer.db数组中,而数据库的数量则由 redisServer. dbnum属性保存;
  • 客户端通过修改目标数据库指针,让它指向 redisServer.db数组中的不同元素来切换不同的数据库;
  • 数据库主要由dict和expires两个字典构成,其中dict字典负责保存键值对,而expires字典则负责保存键的过期时间。
  • 因为数据库由字典构成,所以对数据库的操作都是建立在字典操作之上的。
  • 数据库的键总是一个字符串对象,而值则可以是任意一种 Redis对象类型,包括字符串对象、哈希表对象、集合对象、列表对象和有序集合对象,分别对应字符串键、哈希表键、集合键、列表键和有序集合键。
  • expires字典的键指向数据库中的某个键,而值则记录了数据库键的过期时间,过期时间是一个以毫秒为单位的UNIX时间。
  • Redis使用惰性删除和定期删除两种策略来删除过期的键:惰性删除策略只在碰到过期键时才进行删除操作,定期删除策略则每隔一段时间主动查找并删除过期键。
  • 执行SAVE命令或者BGSAVE命令所产生的新RDB文件不会包含已经过期的键。
  • 执行BGREWRITEAOF命令所产生的重写AOF文件不会包含已经过期的键。
  • 当一个过期键被删除之后,服务器会追加一条DEL命令到现有AOF文件的末尾,显式地删除过期键。
  • 从服务器即使发现过期键也不会自作主张地删除它,而是等待主节点发来DEL命令,这种统一、中心化的过期键删除策略可以保证主从服务器数据的一致性。
  • 当 Redis命令对数据库进行修改之后,服务器会根据配置向客户端发送数据库通知。

第 10 章 RDB持久化

1. RDB文件的创建:

        Save和Bgsave命令可以用于生成RDB文件。

2. Save和Bgsave命令的区别:

  • Save命令会阻塞Redis服务器进程,知道RDB文件创建完毕为止,在服务器进程阻塞期间,服务器器不能处理任何命令请求。
  • Bgsave命令会派生出一个子进程,然后由子进程负责创建RDB文件,父进程继续处理命令。

3. RDB文件的载入:

  • RDB文件的载入是在服务器启动时自动执行的,所有Redis并没有专门用于载入RDB文件的命令。
  • 如果服务器开启了AOF持久化功能,服务器会优先使用AOF文件来还原数据库状态(AOF文件的更新频率比RDB文件更新频率高)。
  • 只有在AOF持久化功能处于关闭状态时,服务器才会使用RDB文件来还原数据库状态。
  • 载入RDB文件的实际工作由rdb.c/rdbLoad函数完成。
  • RDB文件的载入时服务器状态是阻塞状态。

4. 在Bgsave命令执行期间,服务器处理Save、Bgsave、Bgrewriteaof三个命令的方式会有所不同:

  • BGSAVE命令执行期间,客户端发送的SAVE命令会被服务器拒绝,为了避免父进程(服务器进程)和子进程同时执行两个rdb Save调用,防止产生竟争条件。
  • BGSAVE命令执行期间,客户端发送BGSAVE命令会被服务器拒绝,因为同时执行两个BGSAVE命令也会产生竟争条件。
  • BGREWRITEAOF和BGSAVE两个命令不能同时执行(避免两个子进程执行大量的磁盘写入):如果BGSAVE命令正在执行,客户端发送的 BGREWRITEAOF命令会被延迟到BGSAVE命令执行完毕之后执行;如果BGREWRITEAOF命令正在执行,客户端发送的BGSAVE命令会被服务器拒绝。

5. Bgsave支持自动间隔性保存:

6. dirty计数器和lastsave属性:

  • dirty计数器记录距离上一次成功执行SAVE命令或者BGSAVE命令之后,服务器对数据库状态(服务器中的所有数据库)进行了多少次修改(包括写入、刑除、更新等操作)。
  • lastsave属性是一个UNIX时间戳,记录了服务器上一次成功执行SAVE命令或者BGSAVE命令的时间。

7. RDB文件结构:

  • RBD文件的最开头是REDIS部分,这个部分长度为5字节,保存这个“REDIS”五个字符。
  • db_version长度为4字节,它的值是一个字符串表示的整数,这个整数记录了RDB的版本号("0006"代表RDB文件版本为第六版本)。
  • datebase部分包含多个数据库,以及各个数据库中的键值对数据。如果所有数据库的状态为空,那么这部分长度为0字节。
  • EOF常量为1字节,这个常量标志着RDB文件正文内容结束。
  • check_sum是一个8字节长的无符号整数,保存着一个校验和,这个校验和是通过对REDIS、db_version、database、EOF四个部分内容进行计算得出来的。

带有两个非空数据库的结构:

每个非空数据库都保存SELECTDB、db_number、key_value_pairs三个字段:

  • SELECTDB常量的长度为1字节,用来告诉程序接下来要读入数据库号码。
  • db_number保存着一个数据库号码。
  • key_value_pairs部分:不同类型type,又对应不同数据结构的value

8. 分析RDB文件:

        参考教材P133

9. 重点回顾:

  • RDB文件用于保存和还原Redis服务器所有数据库中的所有键值对数据。
  • SAVE命令由服务器进程直接执行保存操作,所以该命令会阻塞服务器。
  • BGSAVE令由子进程执行保存操作,所以该命令不会阻塞服务器。
  • 服务器状态中会保存所有用save选项设置的保存条件,当任意一个保存条件被满足时,服务器会自动执行 BGSAVE命令。
  • RDB文件是一个经过压缩的二进制文件,由多个部分组成。
  • 对于不同类型的键值对,RDB文件会使用不同的方式来保存它们。

第 11 章 AOF持久化

1. 流程:

2. AOF持久化的实现:

  • AOF持久化功能的实现可以分为命令追加(append)、文件写入、文件同步(sync)三个步骤。
  • 追加-->将客户端请求命令追加的缓冲区,写入与同步-->将客户端请求命令从缓存区持久化到AOF文件中。

3. AOF文件的写入与同步:

  • Redis的服务器进程就是一个事件循环(loop),这个循环中的文件事件负责接收客户端的命令请求,以及向客户端发送命令回复,而时间事件则负责执行像serverCron函数这样需求的定时运行函数。
  • 服务器配置的appendfsync选项值(always、everysec、no)来决定AOF写入与同步的方式,它决定了AOF持久化的效率和安全性。
  • appendfsync选项带来的数据丢失问题:always不会丢失,但是效率低;everysec默认使用,会丢失1秒钟数据;no丢失数据量缓存中的数据,同步时间由操作系统决定。

4. AOF文件的载入与数据还原:

5. AOF重写:

  • 作用:解决AOF文件体积膨胀的问题,Redis提供了AOF文件重写(rewrite)功能。
  • 命令:Bgrewriteaof,后台重写
  • 实现:直接取读服务器当前数据库的状态来实现的,不是通过对现有的AOF文件进行任何读取、分析或者写入操作。
  • Tips:为了避免执行命令时,造成客户端输入缓冲区溢出,重写程序处理列表、哈希表、集合、有序集合这四种类型带有多个值事,先会检查元素数量,如果超过REDIS_AOF_REWRITE_ITEMS_PER_CMD(默认64个)常量的值,就会使用多条命令

6. 重点回顾:

  • AOF文件通过保存所有修改数据库的写命令请求来记录服务器的数据库状态。
  • AOF文件中的所有命令都以Redis命令请求协议的格式保存。
  • 命令请求会先保存到AOF缓冲区里面,之后再定期写入并同步到AOF文件。
  • appendfsync选项的不同值对AOF持久化功能的安全性以及Redis服务器的性能有很大的影响。
  • 服务器只要载入并重新执行保存在AOF文件中的命令,就可以还原数据库本来的状态。
  • AOF重写可以产生一个新的AOF文件,这个新的AOF文件和原有的AOF文件所保存的数据库状态一样,但体积更小。
  • AOF重写是一个有歧义的名字,该功能是通过读取数据库中的键值对来实现的,程序无须对现有AOF文件进行任何读入、分析或者写人操作。
  • 在执行BGREWRITEAOF命令时,Redis服务器会维护一个AOF重写缓冲区,该缓冲区会在子进程创建新AOF文件期间,记录服务器执行的所有写命令。当子进程完成创建新AOF文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新AOF文件的末尾,使得新旧两个AOF文件所保存的数据库状态一致。最后,服务器用新的AOF文件替换旧的AOF文件,以此来完成AOF文件重写操作。

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

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

相关文章

B端页面:日志管理页面,简洁实用的设计法门

B端日志管理是指在企业级后台系统中对系统操作日志进行记录、查看和管理的功能。 它的作用主要有以下几点: 1. 安全审计:通过记录用户的操作日志,可以对系统的安全性进行审计和监控,及时发现异常操作和安全漏洞。 2. 故障排查&a…

TEC相关专利研究

每天一篇行业发展资讯,让大家更及时了解外面的世界。 更多资讯,请关注B站/公众号【莱歌数字】,有视频教程~~ 关于TEC在电子行业的部署有很多讨论,这些专利显示了不同发明者关注的一些显著特征。下面的表1列出了本期将审查的专利…

[深度学习] 卷积神经网络CNN

卷积神经网络(Convolutional Neural Network, CNN)是一种专门用于处理数据具有类似网格结构的神经网络,最常用于图像数据处理。 一、CNN的详细过程: 1. 输入层 输入层接收原始数据,例如一张图像,它可以被…

STM32存储左右互搏 模拟U盘桥接QSPI总线FATS读写FLASH W25QXX

STM32存储左右互搏 模拟U盘桥接QSPI总线FATS读写FLASH W25QXX STM32的USB接口可以模拟成为U盘,通过FATS文件系统对连接的存储单元进行U盘方式的读写。 这里介绍STM32CUBEIDE开发平台HAL库模拟U盘桥接Quad SPI总线FATS读写W25Q各型号FLASH的例程。 FLASH是常用的一种…

Maven私服批量上传pom和jar实操

Maven私服上传pom和jar实操-CSDN博客 Maven私服上传jar实操_maven fakepath-CSDN博客 之前写过两篇向maven私服上传jar的操作,看到阅读量还可以,觉得应该有很多人有这个需求,所以这次再放一个大招,通过批量的方式向私服传jar和p…

ChatGPT智能对话绘画系统 带完整的安装源代码包以及搭建教程

系统概述 ChatGPT 智能对话绘画系统是一款集智能语言处理和绘画创作于一体的综合性系统。它利用了深度学习和自然语言处理技术,能够理解用户的意图和需求,并通过与用户的交互,生成富有创意的绘画作品。该系统的核心是一个强大的人工智能模型…

【RAG】PDF Chatbot 个人练手项目

【RAG】PDF Chatbot 个人练手项目 项目的架构和技术选择,以及如何利用它来提升个人的开发能力和理解人工智能技术在文档处理中的应用。 项目截图 后端:FastAPI 应用 功能特性: PDF 文件上传:通过界面或 API,上传 P…

基于weixin小程序新生报到系统的设计

管理员账户功能包括:系统首页,个人中心,学生管理,班级信息管理,师资力量管理,宿舍信息管理,宿舍安排管理,签到信息管理,论坛管理 小程序功能包括:系统首页&am…

Android跨进程调用,Binder线程池溢出导致ANR

Android跨进程调用,Binder线程池溢出导致ANR 如果发生ANR,找到trace.txt 、/data/anr目录下, "main" prio5 tid1 Native| group"main" sCount1 dsCount0 flags1 obj0x72c33e38 self0x78a64c2a00| sysTid1863 nice0 cgr…

Python学习笔记21:进阶篇(十)常见标准库使用之math模块,random模块和statistics模块

前言 本文是根据python官方教程中标准库模块的介绍,自己查询资料并整理,编写代码示例做出的学习笔记。 根据模块知识,一次讲解单个或者多个模块的内容。 教程链接:https://docs.python.org/zh-cn/3/tutorial/index.html 数学 P…

Hi3861 OpenHarmony嵌入式应用入门--LiteOS semaphore作为锁

CMSIS 2.0 接口中的 Semaphore(信号量)是用于嵌入式系统中多线程或中断服务例程(ISR)之间同步和共享资源保护的重要机制。Semaphore 是一种用于控制对多个共享资源访问的同步机制。它可以被看作是一个计数器,用于跟踪可…

计算机组成原理,网络安全,软件工程等上机报告

这些都是学长们当年的战斗,如果需要的话后台联系我

【从0实现React18】 (六) 完成commit提交流程并初步实现react-dom包,完成首屏渲染测试

前面,我们提到 React 更新流程有四个阶段: 触发更新(Update Trigger)调度阶段(Schedule Phase)协调阶段(Reconciliation Phase)提交阶段(Commit Phase) 之前…

并发编程理论基础——合适的线程数量和安全的局部变量(十)

多线程的提升方向 主要方向在于优化算法和将硬件的性能发挥到极致想要发挥出更多的硬件性能,最主要的就是提升I/O的利用率和CPU的利用率以及综合利用率操作系统已经解决了磁盘和网卡的利用率问题,利用中断机制还能避免 CPU 轮询 I/O 状态,也提…

【机器学习】在【R语言】中的应用:结合【PostgreSQL数据库】的【金融行业信用评分模型】构建

目录 1.数据库和数据集的选择 1.准备工作 2.PostgreSQL安装与配置 3.R和RStudio安装与配置 2.数据导入和预处理 1.连接数据库并导入数据 1.连接数据库 2.数据检查和清洗 1.数据标准化 2.拆分训练集和测试集 3.特征工程 1.生成新特征 2.特征选择 4.模型训练和评估…

使用Tailwindcss之后,vxe-table表头排序箭头高亮消失的问题解决

环境 vue2.7.8 vxe-table3.5.9 tailwindcss/postcss7-compat2.2.17 postcss7.0.39 autoprefixer9.8.8 问题 vxe-table 表格表头 th 的排序箭头在开启正序或逆序排序时,会显示蓝色高亮来提示用户表格数据处在排序情况下。在项目开启运行了tailwindcss之后&#xff0…

数据集的未来:如何利用亮数据浏览器提升数据采集效率

目录 一、跨境电商的瓶颈1、技术门槛2、语言与文化差异3、网络稳定性4、验证码处理和自动识别5、数据安全6、法规和合规 二、跨境电商现在是一个合适的商机吗?三、数据集与亮数据浏览器1、市场分析2、价格监控3、产品开发4、供应链优化5、客户分析 四、亮数据浏览器…

上海计算机学会2020年3月月赛C++丙组T4连乘问题

题目描述 给定 a1​,a2​,⋯,an​,请计算一组乘积,记为P1​,P2​,⋯,Pn​,其中 Pi​ 的定义如下: 也就是说,Pi​ 是 a1​ 到 an​ 的连乘再除去 ai​。由于答案可能比较大,输出每个 Pi​ 模 10000 的余数。…

算法05 模拟算法之二维数组相关内容详解【C++实现】

大家好,我是bigbigli,前面一节我们一节讲过一维数组的模拟了,如果还没看的话,可以👉点击此处。模拟算法还有很多内容需要讲,比如图像、日期相关的模拟算法,后续将继续更新,今天先来讲…

代码随想录——跳跃游戏Ⅱ(Leetcode 45)

题目链接 贪心 class Solution {public int jump(int[] nums) {if(nums.length 1){return 0;}int count 0;// 当前覆盖最远距离下标int curDistance 0;// 下一步覆盖距离最远下标int nextDistance 0;for(int i 0; i < nums.length; i){nextDistance Math.max(nums[…