Redis中String类型数据扩容原理分析
大家好,我是 V 哥。在 Java 中,我们有动态数组ArrayList,当插入新元素空间不足时,会进行扩容,好奇 Redis 中的 String 类型,C 语言又是怎样的实现策略,带着疑问,咱们来了解一下。
最适合Java 新手入门的教程:http://t.csdnimg.cn/3auFZ
在Redis中,String类型数据的扩容主要涉及到SDS(Simple Dynamic String)的内存分配机制。SDS是Redis用来存储字符串的数据结构,它在C语言的字符数组基础上进行了封装,以支持动态扩展长度的功能。
当对一个String类型的值进行修改操作(如增加内容)时,如果现有的空间不足以容纳新的数据,Redis就会进行扩容。
在Redis中,sdsMakeRoomFor
函数是用来扩展SDS字符串的缓冲区的。这个函数的目的是确保SDS字符串有足够的空间来追加新的数据。以下是sdsMakeRoomFor
函数的实现逻辑:
-
检查现有空间:首先,函数会检查SDS字符串的现有空闲空间(由
sdshdr
结构的free
属性记录)是否足够容纳额外的数据。如果足够,函数直接返回,不需要进行扩容。 -
计算新长度:如果现有空间不足,函数会计算出需要的新长度。这通常是现有长度加上要添加的数据的长度。
-
确定扩容策略:Redis采用一种预分配策略来优化内存使用和提高性能。如果新长度小于
SDS_MAX_PREALLOC
(通常为1MB),那么Redis会将新长度扩大两倍,以减少频繁的内存分配操作。如果新长度大于或等于SDS_MAX_PREALLOC
,则会一次性分配足够的空间,避免每次扩容都只增加少量空间,导致性能下降。 -
内存分配:根据新的扩容策略,Redis会使用
s_realloc_usable
(如果类型未变)或s_malloc_usable
(如果类型变化,需要移动数据)来分配新的内存空间。 -
更新SDS头部:在新的内存空间分配完成后,Redis会更新SDS的头部信息,包括长度、空闲空间等,并复制原有数据到新的内存位置。
-
处理类型变化:如果扩容导致SDS的类型发生变化(例如,从
SDS_TYPE_8
变为SDS_TYPE_16
),Redis还需要更新SDS的编码类型,并可能需要移动数据到新的内存位置。
在Redis 7.0版本中,SDS的内存布局有所变化,不再使用free
属性,而是使用alloc
属性来记录分配的空间总长度,len
属性记录已使用的字符串长度。因此,alloc
和len
的差值就代表了空闲空间的大小。这种设计使得SDS在内存布局上更加紧凑,取消了编译器的对齐,以节省内存空间。
sdsMakeRoomFor
函数的具体实现如下:
sds _sdsMakeRoomFor(sds s, size_t addlen, int greedy) {void *sh, *newsh;size_t avail = sdsavail(s);size_t len, newlen, reqlen;char type, oldtype = s[-1] & SDS_TYPE_MASK;int hdrlen;size_t usable;/* 如果有足够的剩余空间,直接返回 */if (avail >= addlen) return s;len = sdslen(s);sh = (char*)s-sdsHdrSize(oldtype);reqlen = newlen = (len+addlen);assert(newlen > len); /* Catch size_t overflow *///判断是否为greedy模式(为1表示greedy模式)//是将新长度翻倍还是额外增加`SDS_MAX_PREALLOC`if (greedy == 1) {if (newlen < SDS_MAX_PREALLOC)newlen *= 2;elsenewlen += SDS_MAX_PREALLOC;}type = sdsReqType(newlen);/* 如果类型是SDS_TYPE_5,但是用户正在追加字符串,那么使用SDS_TYPE_8 */if (type == SDS_TYPE_5) type = SDS_TYPE_8;hdrlen = sdsHdrSize(type);assert(hdrlen + newlen + 1 > reqlen); /* Catch size_t overflow */if (oldtype == type) {newsh = s_realloc_usable(sh, hdrlen+newlen+1, &usable);if (newsh == NULL) return NULL;s = (char*)newsh+hdrlen;} else {newsh = s_malloc(hdrlen+newlen+1);if (newsh == NULL) return NULL;memcpy((char*)newsh+hdrlen, s, len+1);s_free(sh);s = (char*)newsh+hdrlen;s[-1] = type;sdssetlen(s, len);}usable = usable-hdrlen-1;if (usable > sdsTypeMaxSize(type))usable = sdsTypeMaxSize(type);sdssetalloc(s, usable);return s;
}
这个函数首先检查是否有足够的空间来追加数据,如果没有,则根据当前的字符串长度和需要追加的数据长度来计算新的总长度。如果启用了greedy
模式,它会根据是否超过SDS_MAX_PREALLOC
来决定是将新长度翻倍还是额外增加SDS_MAX_PREALLOC
。然后,它会根据新的总长度来确定新的SDS类型,并分配新的内存空间。如果SDS的类型没有变化,它会使用s_realloc_usable
来扩展现有的内存空间;如果类型变化了,它会使用s_malloc
来分配新的内存空间,并将旧数据复制到新位置。最后,它会更新SDS头部信息,包括长度和分配的空间大小。
注意一下哈,在Redis 7.0版本之前的SDS实现和7.0版本之后的实现有哪些变化呢?
在Redis 7.0版本之前,SDS(Simple Dynamic String)的实现主要包括一个头部结构struct sdshdr
,其中包含了记录已使用空间的len
字段,记录未使用空间的free
字段,以及一个字符数组buf
用于存储字符串。这种设计允许SDS在O(1)时间复杂度内获取字符串长度,并且通过维护free
字段来减少内存重分配的次数,提高性能。
然而,在Redis 7.0版本中,SDS的实现发生了一些变化。首先,引入了一个新的字段flags
,它是一个单字节的字段,用于存储SDS的类型信息。这使得SDS的结构更加紧凑,取消了编译器的对齐,节省了内存空间。其次,free
字段被移除,取而代之的是alloc
字段,它表示SDS的总分配空间。因此,alloc
和len
的差值就代表了空闲空间的大小。这种设计使得SDS在内存布局上更加紧凑,同时保持了动态扩展长度的功能。
在Redis 7.0版本中,SDS的类型被定义为以下几种:
SDS_TYPE_5
:长度小于32的字符串,使用flags
的5个最高位存储长度。SDS_TYPE_8
:长度在1到255之间的字符串,使用1个字节存储长度。SDS_TYPE_16
:长度在256到65535之间的字符串,使用2个字节存储长度。SDS_TYPE_32
:长度在65536到4294967295之间的字符串,使用4个字节存储长度。SDS_TYPE_64
:长度大于4294967295的字符串,使用8个字节存储长度。
这种设计允许SDS根据字符串的实际长度选择最合适的头部类型,从而节省内存。例如,对于短字符串,可以使用SDS_TYPE_5
类型的头部,它不包含单独的长度和分配字段,而是将这些信息存储在flags
字段中。
此外,Redis 7.0版本中的SDS实现还包括了一些其他的优化,例如,使用__attribute__ ((__packed__))
来确保结构体在内存中紧凑排列,以及通过s_malloc
和s_realloc
等函数来管理内存分配,确保内存对齐的同时,也提供了灵活的内存管理。
咱们很显然可以看出,Redis 7.0版本对SDS的实现进行了优化,使其更加紧凑和高效,同时也保持了SDS的动态扩展和二进制安全的特性。这些改进有助于提高Redis在处理大量数据时的性能和资源利用率。关注威哥爱编程,学习代码乐无边
相关文章:

Redis中String类型数据扩容原理分析
大家好,我是 V 哥。在 Java 中,我们有动态数组ArrayList,当插入新元素空间不足时,会进行扩容,好奇 Redis 中的 String 类型,C 语言又是怎样的实现策略,带着疑问,咱们来了解一下。 最…...

智能码二维码zhinengma.cn在供应链管理中有哪些优势?
智能码二维码在供应链管理中具有以下优势: 一、提高信息透明度 通过为每个产品或包装分配唯一的二维码,可以实现供应链各环节信息的实时共享。这有助于提高供应链的信息透明度,让各方都能及时了解产品的状态和位置。 二、加强追溯能力 智…...

代理商培训新策略:利用内部知识库提升培训效果
在当今竞争激烈的市场环境中,代理商作为企业与终端消费者之间的桥梁,其专业能力和服务质量直接影响着企业的市场表现和品牌形象。因此,对代理商进行系统而高效的培训,提升其业务技能和服务水平,成为企业不可忽视的重要…...

Redis 哨兵模式下DB库操作审计
Redis Sentinel集群环境 主机版本模式NodeSentinelredis-sentinel-node-06.2.12哨兵MasterYesredis-sentinel-node-16.2.12哨兵SlaveYesredis-sentinel-node-26.2.12哨兵SlaveYes 架构设计 命令行&程序验证 1、在redis-sentinel-node-1上使用redis-cli 连接redis-sentine…...

latex公式输入-矩阵
矩阵输入: 例1 \begin{bmatrix}1& 4&3 &5 \\\frac{1}{4} &1& \frac{1}{2}& 2\\\frac{1}{3}&2&1& \frac{5}{3} \\\frac{1}{5}& \frac{1}{2}& \frac{3}{5}&1 \end{bmatrix} 运行结果: 例2 \begin{bm…...

NSSCTF-WEB-easy_eval
目录 前言 正文 思路 序列化构造 后渗透 思路点1:Redis 思路2:蚁剑插件绕过disable_functinons 结尾 作者的其他文章 前言 说是easy,实际很difficult 正文 思路 <?php class A{public $code "";function __call($method,$args){//最后执行命令eval($th…...

交通目标识别数据集YOLO 模型 ui界面✓图片数量15000,xml和txt标签都有 11类 交通道路车辆行人红黄绿数据集 红绿灯数据集 交通信号数据集
YOLO交通目标识别 数据集 模型 ui界面 ✓图片数量15000,xml和txt标签都有; ✓class:biker,car,pedestrian,trafficLight,trafficLight-Green,trafficLight-GreenLeft, tr…...

买卖股票的最佳时机 题解
买卖股票的最佳时机 问题描述 给定一个数组 prices,其中 prices[i] 表示第 i 天的股票价格。你只能选择某一天买入股票,并选择未来的某一天卖出股票,设计一个算法来计算你所能获取的最大利润。 限制条件: 只能进行一次交易&…...

微信小程序路由跳转的区别及其常见的使用场景
在微信小程序中,页面路由跳转的实现有几种常用方式,不同的跳转方式适用于不同的使用场景。下面是几种跳转方法的区别及其在实际项目中的应用场景。 1. wx.navigateTo 简介:保留当前页面并跳转到指定页面,最多保留10个页面的历史记…...

麒麟桌面版v10 SP1以docker方式安装达梦数据库
安装docker 0.切换root用户(可以不切换,但要注意权限问题,我是用root) ymym-pc:~/桌面$ whoami ym ymym-pc:~/桌面$ sudo -i rootym-pc:~# whoami root rootym-pc:~# 1.查看系统版本 [rootlocalhost opt]# cat /etc/os-release…...

KNN的 k 设置的过大会有什么问题
在KNN(K-Nearest Neighbors)算法中,K值的选择对模型的性能和预测结果有着重要影响。如果K值设置得过大,可能会出现以下问题: 欠拟合:当K值过大时,模型会考虑过多的邻近点实例,甚至会…...

Star Tower:智能合约的安全基石与未来引领者
在区块链技术的快速发展中,智能合约作为新兴的应用形式,正逐渐成为区块链领域的重要组成部分。然而,智能合约的可靠性问题一直是用户最为关心的焦点之一。为此,Star Tower以其强大的技术实力和全面的安全保障措施,为智…...

2024-NewStarCTF-WEEK1
web headach3 提示head,抓包查看响应头,得到flag flag值:flag{You_Ar3_R3Ally_A_9ooD_d0ctor} 会赢吗 第一段:源码里找到第一段flag,ZmxhZ3tXQTB3 第二段:分析可知需要在控制台调用revealFlag函数向服务…...

大数据面试题整理——Zookeeper
系列文章目录 大数据面试题专栏点击进入 文章目录 系列文章目录大数据面试题专栏点击进入 1. 什么是 Zookeeper?2. Zookeeper 的特点有哪些?3. Zookeeper 的数据模型是怎样的?4. Zookeeper 的工作流程是怎样的?5. Zookeeper 如何…...

图书库存管理:Spring Boot驱动的进销存系统
1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及,互联网成为人们查找信息的重要场所,二十一世纪是信息的时代,所以信息的管理显得特别重要。因此,使用计算机来管理图书进销存管理系统的相关信息成为必然。开…...

用增结算数仓化改造:在/离线调度系统的构建与应用
导读 移动运营推广平台(OPS)承载着百度内部移动应用/移动搜索业务的用户增长预算的全流程结算线上化管控功能,为了解决用增业务发展规模扩大、原有技术架构老旧、无离线数仓系统等一系列的问题,针对全域结算数据启动了整体的架构…...

施磊C++高级进阶课程 | 学习笔记 | 博客汇总
施磊C高级进阶课程 | 学习笔记 | 博客汇总 施磊C | 进阶学习笔记 | 1.对象的应用优化、右值引用的优化-CSDN博客 施磊C | 进阶学习笔记 | 2.智能指针-CSDN博客 施磊C | 进阶学习笔记 | 3.绑定器和函数对象、lambda表达式-CSDN博客 施磊C | 进阶学习笔记 | 4.c11内容汇总、多…...

学习threejs,拉伸几何体THREE.TubeGeometry管道
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️拉伸几何体THREE.TubeGeome…...

day01-Qt5入门
day01-Qt5入门 窗体应用 1.1 窗体基类说明 创建项目在details中编辑器提供了三个基类,分别是 QMainWindows、Qwidget、QDialog 1、 QMainWindow QMainWindow 类提供一个有菜单条、锚接窗口(例如工具条)和一个状态条的主应用 程序窗口。…...

AnaTraf | 利用多点关联数据分析和网络关键KPI监控提升IT运维效率
目录 什么是多点关联数据分析? 多点关联数据分析的运用场景 监控网络关键KPI的重要性 典型的网络关键KPI 案例分析:利用多点关联数据分析和KPI监控解决网络性能问题 结语 AnaTraf 网络性能监控系统NPM | 全流量回溯分析 | 网络故障排除工具AnaTraf…...

图书库存控制:Spring Boot进销存系统的应用
2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统,它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等,非常…...

Python 工具库每日推荐 【pyspider 】
文章目录 引言网络爬虫的重要性今日推荐:pyspider 网络爬虫框架主要功能:使用场景:安装与配置快速上手示例代码代码解释实际应用案例案例:爬取新闻网站的文章案例分析高级特性使用代理处理 JavaScript 渲染的页面扩展阅读与资源优缺点分析优点:缺点:总结【 已更新完 Type…...

【C语言教程】【常用类库】(十五)网络编程 - <sys/socket.h> 和 <netinet/in.h>
15. 网络编程 - <sys/socket.h> 和 <netinet/in.h> 网络编程在C语言中是通过套接字来实现的,套接字提供了进程间通信的端点。C语言的网络编程涉及到创建套接字、绑定地址、监听和接收数据。以下是网络编程的关键概念和基本实现方法。 15.1. 套接字基础…...

正点原子讲解SPI学习,驱动编程NOR FLASH实战
配置SPI传输速度时,需要先失能SPI,__HAL_SPI_DISABLE,然后操作SPI_CR1中的波特率设置位,再使能SPI, NM25Q128驱动步骤 myspi.c #include "./BSP/MYSPI/myspi.h"SPI_HandleTypeDef g_spi1_handler; /* SPI句柄 */void spi1_init(void) {g_spi…...

低代码开发助力中小企业数字化转型难度持续降低
随着信息技术的飞速发展,数字化转型已成为企业持续发展的关键驱动力。对于中小企业而言,数字化转型不仅意味着提升效率、降低成本,更是实现业务模式创新和市场竞争力提升的重要途径。然而,传统软件开发模式的高成本、长周期和复杂…...

【Linux】:线程控制
朋友们、伙计们,我们又见面了,本期来给大家带来线程控制相关代码和知识点,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成! C 语 言 专 栏:C语言:从入门到精通 数…...

大数据-174 Elasticsearch Query DSL - 全文检索 full-text query 匹配、短语、多字段 详细操作
点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…...

Spring Boot视频网站:构建可扩展的视频服务平台
6系统测试 为了保证所开发出来的系统质量过关,让所开发出来的系统具备可靠性并能够投入运行使用,这就需要进行系统开发的最后一个关键步骤,那就是系统测试。可以说系统测试就是对系统开发前面的步骤,比如系统分析与设计等进行复查…...

护眼台灯横评:书客、柏曼、明基哪款使用体验好,又能护眼?
如果你使用过护眼台灯,就太能理解为什么护眼台灯会诞生了。护眼台灯确实有一定的护眼作用,光线柔和不刺眼,许多护眼台灯还有智能调光、定时休息等人性化功能。在当今这个数字化时代,长时间面对电脑屏幕或埋头于书本已成为许多人的…...

RDMA笔记
目录 1. RDMA简介1.1. 比较Socket与RDMA的通信1.2. RDMA优势1.3. RDMA 2. RDMA基本元素2.1. QPSQ, SQE & RQ, RQEQPNQPC 2.2. CQ2.3. MR2.4. PD 3. RDMA基本操作3.1. Send & Receive3.2. RDMA Write3.3. RDMA Read 阅读RDMA相关资料,从硬件开发角度对RDMA作…...