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

Redis EmbeddedString

前言

Redis 写入键值对时,首先会先创建一个 RedisObject 对象来存储 Value。
如果写入的 Value 是字符串,那么 Redis 会再根据写入的字符串长度,来创建对应的 sdshdr 来存储字符串,最后把 RedisObject 的 ptr 指针指向 sdshdr。
我们来分析下这个过程,首先创建 RedisObject 需要分配一次内存,创建 sdshdr 又需要再分配一次内存。
由此可见,如果 RedisObject 和 sds 分开存储的话,需要多分配一次内存,内存碎片化的概率也会增加。
Redis 本着节省内存的原则,还可以做出哪些优化呢?

EmbeddedString

先回顾一下 RedisObject 结构,前三个属性合计占用 4 字节,refcount 占用 4 字节,ptr 指针占用 8 字节,合计 16 字节。

typedef struct redisObject {unsigned type:4;unsigned encoding:4;unsigned lru:LRU_BITS;int refcount;void *ptr;
} robj;

Redis 默认使用 jemalloc 内存分配器,分配的内存必须是 2 的幂次方大小,比如你要申请 5 字节,jemalloc 会给你分配 8 字节;你要申请 10 字节,jemalloc 会分配 16 字节。
基于这个规则,Redis 就想,能不能创建 RedisObject 的同时就分配多一点内存,好存储接下来的字符串呢?当然可以,那申请多大合适呢?首先肯定要是 2 的幂次方数,32 字节有点太小了,因为 sdshdr8 头部就占用了 3 字节,再加上一个 ‘\0’ 结尾符,真正留给字符串的空间就剩 12 字节了,显然不实用,很容易溢出。
32 不够,那只能再往上加了,64 字节,可以存储 44 字节的字符串,基本够用了。恰巧在 x86 架构下,CPU 缓存行的大小一般也是 64 字节,刚好可以完整加载。

所以,现在我们得出一个结论,如果写入的字符串长度在 44 以内,那么就可以在创建 RedisObject 时直接申请 64 字节,然后把 sds 直接挨着 RedisObject 末尾写入,这样就可以避免再分配一次内存,内存的碎片率也能得到优化。

我们看看 Redis 具体是怎么做的,创建字符串对象的方法是createStringObject()

#define OBJ_ENCODING_EMBSTR_SIZE_LIMIT 44
robj *createStringObject(const char *ptr, size_t len) {if (len <= OBJ_ENCODING_EMBSTR_SIZE_LIMIT)return createEmbeddedStringObject(ptr,len);elsereturn createRawStringObject(ptr,len);
}

常量 OBJ_ENCODING_EMBSTR_SIZE_LIMIT 的值刚好就是 44,这证明了我们的猜想。如果字符串长度超过了 44,Redis 也只能分配 sds 空间,单独存储字符串了,对应的方法是createRawStringObject()

这种和 RedisObject 存储在一起的字符串,Redis 给它取名叫 EmbeddedString,创建的方法是createEmbeddedStringObject()

robj *createEmbeddedStringObject(const char *ptr, size_t len) {robj *o = zmalloc(sizeof(robj)+sizeof(struct sdshdr8)+len+1);struct sdshdr8 *sh = (void*)(o+1); // sh 指向 RedisObject末尾 即sdshdr开始位置o->type = OBJ_STRING; // 对外类型还是 stringo->encoding = OBJ_ENCODING_EMBSTR; // 区别于普通sds,这里的编码类型是8o->ptr = sh+1; // ptr 指向sdshdr末尾 即字符串开始位置o->refcount = 1;// 设置lru时钟if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) {o->lru = (LFUGetTimeInMinutes()<<8) | LFU_INIT_VAL;} else {o->lru = LRU_CLOCK();}// 设置sdshdr头sh->len = len;sh->alloc = len;sh->flags = SDS_TYPE_8;if (ptr == SDS_NOINIT)sh->buf[len] = '\0';else if (ptr) {memcpy(sh->buf,ptr,len);sh->buf[len] = '\0';} else {memset(sh->buf,0,len+1);}return o;
}

创建 EmbeddedString 的步骤如下:

  • 先分配内存,大小是 RedisObject 大小 + sdshdr8 大小 + 字符串长度 + 1个’\0’字符的长度
  • sh 指针指向 sdshdr 的起始位置
  • RedisObject->ptr 指针指向字符数组的起始位置,在介绍 sds 的说过了,指针左移一位就能读到 flags
  • 给 RedisObject 对象设置 lru 时间戳
  • 设置 sdshdr 头数据

尾巴

当我们向 Redis 写入 string 数据时,Redis 首先要创建 RedisObject 分配一次内存,然后再创建 sds 时又要二次分配内存,这样不仅浪费内存,还会增加碎片化率。Redis 结合 jemalloc 的分配策略,以及 x86 架构下的缓存行大小,决定如果写入的字符串长度较小,就一次直接申请 64 字节的内存,剩下 44 字节的长度用来存储字符串,这种字符串的存储方式也被称作 嵌入式字符串。

相关文章:

Redis EmbeddedString

前言 Redis 写入键值对时&#xff0c;首先会先创建一个 RedisObject 对象来存储 Value。 如果写入的 Value 是字符串&#xff0c;那么 Redis 会再根据写入的字符串长度&#xff0c;来创建对应的 sdshdr 来存储字符串&#xff0c;最后把 RedisObject 的 ptr 指针指向 sdshdr。 …...

SpringMVC之WEB-INF下页面跳转@ModelAttributeIDEA tomcat控制台中文乱码问题处理

WEB-INF下页面跳转 ModelAttribute来注解非请求处理方法 用途&#xff1a;预加载数据&#xff0c;会在每个RequestMapping方法执行之前调用。 特点&#xff1a;无需返回视图&#xff0c;返回类型void IDEA tomcat控制台中文乱码问题处理 复制此段代码&#xff1a;-Dfile.e…...

利用ChatGPT练习口语

目录 ChatGPT 这两天发布了一个激动人心的新功能&#xff0c;App端&#xff08;包括iOS和Android&#xff09;开始支持语音对话以及图片识别功能。 这两个功能一如既往的优先开放给Plus用户使用&#xff0c;现在将App更新到最新版本&#xff0c;就能体验。 为什么说激动人心&a…...

【Django 01】环境搭配与项目配置

1. 介绍 https://github.com/Joe-2002/sweettalk-django4.2#readme Django 是一个使用 Python 编写的开源 Web 应用程序框架&#xff0c;它提供了一套用于快速开发安全、 可扩展和高效的 Web 应用程序的工具和功能。Django 基于 MVC&#xff08;Model-View-Controller&#xf…...

PyCharm配置运行参数

...

ChatGPT AIGC 实现Excel 交叉查找 Index+match 函数

行与列交叉多条件查找需求如下: 这个需求要使用Excel中最经典的组合函数Index+match函数。 函数公式可以交给ChatGPT AIGC来实现。 Prompt: 有一个表格A列为品牌,B列为月份,C列为销量,61行数据,请写出Excel函数公式根据E3单元格的品牌与F2单元格的月份查找对应的销量,…...

【前端学习】—多种方式实现数组拍平(十一)

【前端学习】—多种方式实现数组拍平&#xff08;十一&#xff09; 一、数组拍平 数组拍平也叫数组扁平化、数组拉平、数组降维&#xff0c;指的是把多维数组转化为一维数组。 二、使用场景 复杂场景下的数据处理&#xff08;echarts做大屏数据展示&#xff09; 三、如何实…...

智慧远程医疗服务:从零开始搭建互联网医院APP

互联网医院APP作为远程医疗服务的一部分&#xff0c;正在为患者和医生带来更便捷的医疗体验。本文将探讨如何从零开始构建一个互联网医院APP&#xff0c;包括关键步骤、技术要点和挑战。 一、确定项目目标和范围 在开始之前&#xff0c;您需要明确定义您的互联网医院APP的目标…...

ADAS可视化系统,让自动驾驶更简单 -- 入门篇

随着车载芯片的升级、技术的更新迭代&#xff0c;可视化ADAS逐渐变成汽车的标配走入大家的生活中&#xff0c;为大家的驾车出行带来切实的便捷。那么你了解HMI端ADAS的实现过程吗&#xff1f;作为ADAS可视化系统的入门篇&#xff0c;就跟大家聊一聊目前较常见的低消耗的一种ADA…...

探索低代码技术

低/无代码的高速发展&#xff0c;属于软件市场的选择&#xff0c;相较于传统编写代码的开发方式&#xff0c;低/无代码开发效率高、投入成本低、技术门槛也更低&#xff0c;未来更多软件应用将使用低/无代码技术完成&#xff0c;这也是趋势。 身为开发人员经常需要花大量时间在…...

头歌的数据库的第二次作业的答案

目录 MySQL-视图 第1关&#xff1a;创建所有保险资产的详细记录视图 第2关&#xff1a;基于视图的查询 MySQL数据库 - 连接查询 第1关&#xff1a;内连接查询 第2关&#xff1a;外连接查询 第3关&#xff1a;复合条件连接查询 MySQL数据库 - 子查询 第1关&#xff1a;…...

基于R329 SOC智能音响开发编译环境搭建

R329智能音响开发编译环境搭建 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务, R329编译命令 source build/envsetup.sh lunch make -j4 pack 编译工程选择 baidu_panshan...

libplctag开源库的API介绍

文章目录 1 开源库概要2 API介绍2.1 Tag Model&#xff08;标签模型&#xff09;2.2 Status Codes&#xff08;状态码&#xff09;2.3 Versions and Checking Library Compatibility&#xff08;版本和检查库的兼容性&#xff09;2.4 Tag Life Cycle&#xff08;标签生命周期&a…...

智能化安全巡更巡查系统—提升安全管理效率

传统的巡检都是手工完成&#xff0c;记录、拍照&#xff0c;回到办公室打印表单再交给作业队伍整改&#xff0c;再去现场核实复查&#xff0c;流程繁琐&#xff0c;效率低。而且大部分工地为了减少麻烦&#xff0c;人员往往都是口头沟通&#xff0c;存在很大质量风险&#xff0…...

SAP MM学习笔记36 - 释放支付保留的发票

SAP中&#xff0c;请求书照合之后&#xff0c;发现不一致&#xff0c;就会支付保留。 支付保留&#xff0c;可以参考如下文章。 SAP MM学习笔记34 - 请求书照合中的支付保留&#xff08;发票冻结&#xff09;_东京老树根的博客-CSDN博客 当然发现不一致之后&#xff0c;如果不…...

MySQL数据库的ID列添加索引

要为MySQL数据库的ID列添加索引&#xff0c;可以使用以下语法&#xff1a; ALTER TABLE table_name ADD INDEX index_name (id);其中&#xff0c;table_name是要添加索引的表名&#xff0c;index_name是索引的名称&#xff0c;id是要添加索引的列名。 例如&#xff0c;如果要…...

LuaJIT编写的解析十六进制数据

以下是使用LuaJIT编写的解析十六进制数据并将uint16转换为JSON的示例代码&#xff1a; local ffi require("ffi") local bit require("bit") local cjson require("cjson")-- 定义结构体 ffi.cdef[[typedef struct {uint16_t value;} uint16…...

【SA8295P 源码分析 (一)】09 - XBL Loader 加载 QSEE、SEC、CPUCPFW、QHEE、APPSBL过程分析

【SA8295P 源码分析】09 - XBL Loader 加载 QSEE、SEC、CPUCPFW、QHEE、APPSBL过程分析 一、QSEE二、SEC三、CPUCPFW四、QHEE五、APPSBL系列文章汇总见:《【SA8295P 源码分析 (一)】系统部分 文章链接汇总 - 持续更新中》 本文链接:《【SA8295P 源码分析 (一)】09 - XBL Load…...

封装一个Element-ui生成一个可行内编辑的表格(vue2项目)

这个封装的是一个供整个项目使用的表格,可多次复用.放在一个全局使用的公共组件文件下. 大致功能介绍,封装自定义指令,点击获得焦点,显示输入框,失去焦点显示文本内容,类型是字典决定类型,图片可以显示图片名还是上传图片 子组件 <script> export default {props: {//生…...

hanniman 1v1 咨询

‍ 一共4种可选方案&#xff0c;3个To C&#xff08;面向AI产品经理的职业规划诊断、求职内推套餐、模拟面试&#xff09;&#xff0c;1个To B&#xff08;面向AI企业/投资机构/券商等&#xff09;。 方案A&#xff1a;职业规划诊断 适合人群&#xff1a;AI产品经理 or 想转型A…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...