实践篇 11 | 万金油的string,为什么不好用了

11 | “万金油”的String,为什么不好用了? Redis核心技术与实战 实践篇 11 | “万金油”的String,为什么不好用了? 阅读详情

string类型的内存空间消耗问题。

一个图片存储系统,需要

  • 快速记录图片ID和图片在存储系统中保存的ID(存储对象id)
  • 根据图片ID查找图片存储id

图片数量巨大,用10位数表示图片ID和存储对象ID,如图片ID:1101000051,存储系统中对象ID:3301000051

photo_id: 1101000051
photo_obj_id: 3301000051

键-单值模式,单值指的是键值对的值不是集合。和string类型提供的“一键一值”的保存形式刚好。

且String类型可保存二进制字节流,把数据转成二进制字节数组即可存储,所以说其“万金油”。

刚开始,存了1亿张图,用大约6.4G内存。随着图片数量增加,遇到了大内存redis实例因生成RDB而响应变慢的问题。需优化内存占用。

String类型为什么内存开销大?

刚才的案例中:一个图片ID和图片存储对象的记录平均使用64字节。(1亿张~6.4GB)

实际,最多16字节即可存储(各10位的数字,可用8字节的Long类型)。但String类型额外记录数据长度,空间使用等元数据占据了空间,元数据开销就变大了。

64位有符号整数,String类型存储为一个8字节的Long类型整数,即int编码方式存储。

包含字符的数据,String类型就会用简单动态字符串(SDS)存储,

除了SDS还有一个RedisObject结构体记录元数据(最近访问时间、被引用次数)。实际String类型的存储结构如下,分为三种编码类型。

 

 基于该知识分析,图片ID和存储系统中对象ID,都采用int编码存储,值总共是32字节。还剩32字节是全局hash中的entry空间。

因此抛开key的大小,有效信息只需16字节,但实际要64字节,其余48字节没有实际存数据。换算后1亿图片大约4.8G浪费了。

用什么数据结构可以节省内存?

 

Redis底层有一个结构,叫压缩列表ziplist,非常省内存。

entry挨个儿放置在内存中,无需额外的指针连接,可节省指针空间。

存储一个图片ID,entry大小为(1+4+1+8)14字节,实际分配16字节。Redis基于压缩列表实现了List,Hash和Sorted Set这样的集合类型,好处是省去了dictEntry开销。用String时,dictEntry耗去了32字节。集合类型,单key对应一个集合空间,只用1个dictEntry,省了内存。 

如何使用集合类型存储单值的键值对?

在保存单值的键值对时,可采用Hash的二级编码方法。将数据拆为两部分,一部分key,一部分value。

以图片ID:1101000060和图片存储对象ID 3302000080 为例,可以把图片ID的前7位(1101000)作为Hash类型的键,后3位(060)和图片存储对象ID作为Hash类型集合中的key和value。

127.0.0.1:6379 > info memory
# Memory
used_memory:1039120

127.0.0.1:6379 > hset 1101000 060 3302000080
(integer) 1

127.0.0.1:6379 > info memory
# Memory
used_memory:1039136

一个图片只用了16字节,省了3/4。二级编码中采用的id长度有讲究。Redis的底层结构是压缩列表和hash表。Hash类型设置了用压缩列表保存数据时的两个阈值,一旦超过了就会用哈希表存储数据。

  • hash-max-ziplist-entries:表示用压缩列表保存时哈希集合中的最大元素个数
  • hash-max-ziplist-value:表示用压缩列表保存时哈希集合中单个元素的最大长度。

一旦超过了上述任意阈值,redis会自动把压缩列表转成哈希表,之后再也不会转回来。省内存方面,哈希表没有压缩列表那么高效。

所以刚才的二级编码方案,只用后3位作为键,就可保证hash类型中entry数量不会超过1000个。

小结

打破了对String的认识误区,虽然是“万金油”,但是本身数据不大的时候,元数据开销过大,包括RedisObject,SDS结构,dictEntry的内存开销。

针对这种可以用Hash这种集合类型保存单值键值对,将数据拆两部分,二级编码。

最后有一个工具链:可以知道采用不同类型保存的键值对的内存开销。

思考题

除了String和Hash还有其他合适类型可以应用在本案例所说的图片保存的例子?

VB6数据导出Excel全攻略:6种方法详解与实战避坑指南 数据导出是软件开发中常见的功能需求,尤其在需要与Excel这类通用办公软件进行数据交换的场景下。其核心原理通常涉及数据格式转换与外部组件交互,旨在实现数据在不同系统间的无缝流转。从技术价值看,高效可靠的数据导出能力能极大提升用户体验和系统实用性,尤其在处理遗留系统或特定环境时。在应用场景上,无论是工业控制、财务系统还是内部管理平台,都可能面临将程序内数据导出至Excel进行分析或存档的需求。本文聚焦于在经典的VB6开发环境中,系统梳理并对比了包括CSV生成、自动化对象模型、ADODB直接保存、HTML表格及 阅读详情

相关推荐

redis“万金油”的String,为什么不好用了?

从今天开始,我们就要进入“实践篇”了。接下来,我们会用5节课的时间学习“数据结构”。我会介绍节省内存开销以及保存和统计海量数据的数据类型及其底层数据结构,还会围绕典型的应用场景(例如地址位置查询、时间序列数据库读写和消息队列存取),跟你分享使用Redis的数据类型和module扩展功能来满足需求的具体方案。 今天,我们先了解下String类型的内存空间消耗问题,以及选择节省内存开销的数据类型的解决方案。 先跟你分享一个我曾经遇到的需求。 当时,我们要开发一个图片存储系统,要求这个系统能快速地记录图片I

阅读之后,对你有帮助,那就点个赞再走吧 545

10 | “万金油”的String,为什么不好用了?

我们保存了1亿张图片的信息,用了约6.4GB 的内存,一个图片 ID 和图片存储对象 ID 的记录平均用了64字节。但问题是,一组图片 ID 及其存储对象 ID 的记录,实际只需要16字节就可以了。我们来分析一下。图片 ID 和图片存储对象 ID 都是10位数,我们可以用两个8字节的 Long 类型表示这两个 ID。因为8字节的 Long 类型最大可以表示2的64次方的数值,所以肯定可以表示10位数。但是,为什么 String 类型却用了64字节呢?

谢谢大家的关注 312

微信dat文件解密与转换:Android端异或加密图片还原工具

在Android手机存储中,我们经常遇到无法直接打开的.dat文件,这类文件往往并非损坏,而是经过简单的异或加密处理。异或(XOR)是一种可逆的位运算,只要找到正确的密钥,就能将密文还原为原始数据。这一原理广泛应用于数据保护与格式伪装,尤其在即时通讯软件的本地缓存机制中。了解文件头魔数与异或运算规律,可以帮助我们开发出自动识别密钥、批量还原图片的工具。从技术价值来看,掌握这种处理思路,不仅适用于微信图片缓存恢复,也能扩展到其他私有格式的逆向分析。在工程实践上,开发者还需注意Android分区存储权限、大文件

weixin_34007020的博客 347

Redis:string类型带来的空间消耗过大的问题。

案例:使用Redis的string类型保存图像ID和图片存储对象 ID,图像ID为Key、图片存储对象ID为Value。两者均为10位纯数字。保存1亿对键值消耗空间6.4GB,平均1个键值对消耗64字节。 问题:按理来说8个字节可以表示2的64次方-1,超过了10位数字,案例中键值对加起来消耗16字节也就罢了,为什么消耗了64字节? 回答:除了记录实际数据,String 类型还需要额外的内存空间记录数据长度、空间使用等信息,这些信息也叫作元数据。当实际保存的数据较小时,元数据的空间开销就显得比较大了。 St

weixin_40108561的博客 1861

接上篇,记录一下【Unity 3D对博途PLCSIM的通讯】文章有点长~仔细看,很基础

本文参考链接:西门子PLC丨PROFINET通讯仿真(虚拟通讯)做了一些更详细的优化,本文使用的类库并非原作者使用的类库。 首先,昨天项目已经创建好了,这边也加了一个InputField和一个Button,可以实现简单的读取,ok开始。 放入准备好的通讯类库; 新建一个博途的项目,本次测试使用博途V15,测试环境为虚拟机,Unity运行在本地计算机,建立博途项目流程如下: 新建项目,右键项目-属性-保护-对勾,如图: 不得不说的是,仿真中加密的FB块是无法下载的哦~ 添加CPU...

NS_Speak(IVAV) 8055

EDA课程实验:《数字逻辑电路》实验四___基于Minisys 平台 VIVADO工具与Verilog语言

(4)使用 Verilog HDL 实现一个分频器 clock_div,输入的是系统提供的 100MHz 频率,输出的是 1Hz 频率,占空比是 1:2,(实际上可以用一个加 1 计数器来实现降频,输入的是一个 100MHz 频率的方波,对这 个方波计数 1 亿次刚好到 1 秒(1Hz),题目要求输出频率占空比是 1:2,也就是这个 1Hz 的 方波高电平和低电平各 500ms,可以采用计数到中间值的时候输出电平翻转。(1)1) 拨动 SW1~0 为 01,按下 P4 按钮,GLD1~0 为 01;

ssjy_的博客 1295

Redis学习笔记——万金油string为什么不好用了?

为什么string不好用了 首先string太大了 在Redis中,保存一个string需要使用64字节。如果要保存一个long型整数,原数据只有8字节,而却需要八倍的空间去存储它,这在保存大量数据时时非常不划算的。 为什么需要用的64字节的空间? 因为string不光有自身数据,还有一些“辅助”数据,比如自身的长度以及所占空间,这两个分别需要4字节,目前需要16字节。这些数据称为简单动态字符串(Simple Dynamic String,SDS) 而这之外还需要“包裹一层”RedisObject,由元数

qq_34132502的博客 414

【破局之道】LangChain4j 0.31.0 + Java 8 + Spring Boot:在“过时”环境中构建本地大模型应用的实战指南

本文为使用Java 8和Spring Boot等“过时”技术栈的团队提供了构建本地大模型应用的实战指南。通过采用LangChain4j 0.31.0这一兼容版本,结合Ollama部署本地大模型,开发者无需升级JDK即可在现有项目中快速集成AI能力,实现智能问答、文档摘要等功能,为传统项目注入创新活力。

t4y5u6i7o的博客 557

11 万金油 String,为什么不好用了?

以下将讲解 String 数据类型在 Redis 中的空间消耗问题,其中结合“图片管理系统”这个应用场景,使用 Redis 来实现根据图片的 ID 获取到存储系统中保存的ID(可以直接叫作图片存储对象ID),其中图片 ID 及其图片存储对象 ID 都是用 10 位数字来保存,其中 Redis 系统中存储了一亿个图片,使用的 6.4G 的内存。平均下来,每对图片 ID 与图片存储对象的键值对就需要消耗 64 个字节,然而 10 位数字只需要使用 8 个字节保存,两个加起来仅仅只需要 16 个字节,那么额外的内

wmt0501的博客 589

小红书高时效推荐系统背后的技术升级

在小红书 APP 中,推荐系统的实效性对推荐效果有着特别重要的影响,特别是作为 UGC 平台,小红书的推荐系统如果能更快地捕捉用户与笔记之间的变化和联系,就能够给推荐带来更好的效果。在2021年上半年,首页推荐的召回、粗排、精排的主要模块都保持在天级更新的状态,我们通过持续迭代,将召回 CF 渠道、召回索引更新、召回模型/粗精排模型的训练都做到了分钟级更新,为首页推荐的分发效率带来飞跃式提升,并给业务侧带来非常显著的收益。 小红书站内“最近一天内发布的新笔记”在首页的曝光占比一直很高,这段时间更是快速

REDtech_1024的博客 3521

PICO G2 4K Unity开发环境配置完全指南

VR开发中,Android平台的硬件适配与Unity版本兼容性是基础性技术命题。PICO G2 4K作为基于骁龙845+Android 8.1的专用VR一体机,其开发链路高度依赖特定Unity LTS版本(2020.3.41f1)、NDK r21e及OpenJDK 11等工具链组合,本质是嵌入式Android VR Runtime与Unity IL2CPP ABI的深度对齐问题。该配置方案不仅解决ADB识别、APK签名、Logcat捕获等工程痛点,更支撑手柄6DoF追踪、射线交互、Haptic反馈等核心XR

weixin_30298497的博客 616

11 _ “万金油”的String,为什么不好用了?

从今天开始,我们就要进入“实践篇”了。接下来,我们会用5节课的时间学习“数据结构”。我会介绍节省内存开销以及保存和统计海量数据的数据类型及其底层数据结构,还会围绕典型的应用场景(例如地址位置查询、时间序列数据库读写和消息队列存取),跟你分享使用Redis的数据类型和module扩展功能来满足需求的具体方案。今天,我们先了解下String类型的内存空间消耗问题,以及选择节省内存开销的数据类型的解决方案。先跟你分享一个我曾经遇到的需求。当时,我们要开发一个图片存储系统,要求这个系统能快速地记录图片ID和图片在存

cjh的博客 203

CPU 访问外设的两种核心机制:MMIO(Memory-Mapped I/O) 和 DMA(Direct Memory Access)

BAR和DMA是计算机系统中两种关键的数据传输机制:BAR(基址寄存器)用于CPU与设备间的控制通信,映射设备寄存器便于配置操作;而DMA(直接内存访问)允许设备直接读写系统内存,无需CPU参与大量数据传输。典型场景如NVMe SSD读取数据时,CPU通过BAR下发指令,设备通过DMA高效传输数据到主机内存,最后中断通知CPU。虽然BAR能映射大内存空间,但仍无法替代DMA的高效数据传输功能,两者各司其职——BAR负责控制,DMA专注数据传输,共同实现高性能的硬件交互。

MHD0815的博客 237

redis-11 | “万金油”的String

目录 为什么 String 类型内存开销大 用什么数据结构可以节省内存 如何用集合类型保存单值的键值对

weixin_38805083的博客 111

使用Google Earth Engine下载JRC全球水体数据

通过Google Earth Engine平台和提供的源代码,研究人员和水资源管理者可以方便地获取和利用这一重要的水资源监测数据集,从而开展相关的研究和决策支持工作。要使用Google Earth Engine下载JRC全球水体数据,首先需要在Google Earth Engine平台上进行注册和登录。JRC全球水体数据是由欧洲联合研究中心开发的高分辨率全球水体分类数据集,覆盖了整个地球的陆地和水域。下载完成后,你可以使用各种遥感数据处理软件来打开和分析这些数据,以满足不同的研究和应用需求。

LrlDebug的博客 1157

车载软件架构 —— AUTOSAR Vector SIP包(三)

### 上一篇文章中介绍了AUTOSAR基础软件供应商Vector公司的开发工具链,本文将继续介绍Vector公司的AUTOSAR产品。 ### -> 1、Vector SIP包中的StartApplication ### -> 2、StartApplication如何开始使用

Soly_kun的博客 828

(11)Redis之海量数据下String结构与存储的缺点

文章目录一.背景二.String的底层数据结构1.String怎么进行数据保存的:RedisObjectint编码embstr编码raw编码jemalloc分配2.String缺点三.解决String占用大量内存的方法1.压缩列表 ziplist2.需要解决的问题3.二级编码4.注意关于压缩列表升级为哈希表问题 一.背景 当我们要存储“单值”数据时(例如0123456789:0987654321,可以看作一串id对应着另一串id)这样的数据,我们第一个想到的就是是使用String类型来进行存储。这样我们就

qq_56769991的博客 1797

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Redis核心技术及实战(十.String类型开销大?如何替代?)

十:String类型内存开销大?如何替代? 原文:《11丨“万金油”的String,为什么不好用了?》 例子:存储一个10位数的图片ID和其对应的10位数的图片存储ID,一共存储1亿个这样一个单键值对,我们选用String类型存储时,发现居然用了6.4GB的内存,也就是说平均一个键值对就用了64字节内存,但是,10位数可以用一个8字节的Long型表示,那么一个键值对也就16字节,多出来的48字节去哪了呢? => **除了记录实际数据,String还需要额外的内存空间记录数据长度、空间使用

ZYLer_的博客 357

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

JavaScript六十道万金油面试题

JavaScript非常实用的面试练习题,有答案和详细的解释!

ITjun666的博客 986

【学习记录】Redis 核心技术与实战

个人学习记录。

qq_39640089的博客 338

C++数字转字符串全解析:从to_string到to_chars的性能与实战指南

在C++编程中,类型转换是基础且关键的操作,其中数字到字符串的转换尤为常见。其核心原理是将内存中的二进制数值,按照指定的格式(如十进制、十六进制)和编码规则,转换为人类可读的字符序列。这项技术的价值在于它是数据序列化、日志记录、用户界面显示和网络通信等场景的基石,直接影响程序的正确性、性能和可维护性。从简单的日志输出到高性能的序列化库,都需要根据场景选择合适的转换方法。本文聚焦于C++标准库提供的多种转换方案,深入对比了`std::to_string`、`std::format`、`std::strings

weixin_34310369的博客 309

11 Redis 节省内存的数据结构

11 Redis 节省内存的数据结构前言一、String 类型内存开销大的原因二、计算 String 类型的内存使用量三、节省内存的数据结构四、集合类型保存单值的键值对五、二级编码方法中采用的 ID 长度规则总结 前言 需求:开发一个图片存储系统,要求这个系统能快速地记录图片 ID 和图片在存储系统中保存时的 ID(可以直接叫作图片存储对象 ID)。还要能够根据图片 ID 快速查找到图片存储对象 ID。 因为图片数量巨大,用 10 位数来表示图片 ID 和图片存储对象 ID,例如,图片 ID 为 11010

海陆云的博客 2万+

Redis String底层大揭秘:SDS如何成就高性能奇迹

Redis的String类型底层采用SDS(简单动态字符串)实现,性能远超C字符串(内存节省30%,QPS超百万次)。本文深度解析Redis String的三大编码方式(INT/EMBSTR/RAW)和SDS的五大核心结构,通过内存布局图和源码分析揭示其六大优势:O(1)长度获取、防缓冲区溢出、动态扩容、二进制安全、惰性空间释放和C字符串兼容。同时指出三大使用陷阱(大Key浪费、INT编码误用、EMBSTR边界),并给出"数字用INT、短字符串用EMBSTR、控制44字节临界点"的黄金法

全栈开发工程师 934

Redis 零基础保姆级教程:从会用、爱用到精通

恭喜你!学到这里,你已经掌握了 Redis 的核心概念和常用操作。✅ Redis 是什么,能解决什么问题✅ 如何安装和连接 Redis✅ 五大核心数据类型的用法和场景✅ 发布订阅、事务、管道等进阶功能✅ RDB 和 AOF 持久化的区别✅ Python 操作 Redis 的完整代码✅ 新手常见的 4 个坑和解决方案。

qq_51553749的博客 895
上一篇: 实践篇 12 | 有一亿个 keys 要统计,应该用哪种集合
vectorX
博客等级 码龄11年 37粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值