【redis进阶】Redis String数据类型为什么不好用

news2025/1/20 1:08:29
保存1 亿张10字节图片标识,String结构用了 6.4GB 的内存,为什么?如何优化?

数据量多时,比较占空间

存储数量量较多的时候,可以使用list数据结构来替代String,以二级编码的方式将数据存入redis

为什么String的内存开销大呢?

除了记录数据外,还需记录元数据

buf:字节数组,保存实际数据。为了表示字节数组的结束,Redis 会自动在数组最后加一个“\0”,这就会额外占用 1 个字节的开销。

len:占 4 个字节,表示 buf 的已用长度

alloc:也占个 4 字节,表示 buf 的实际分配长度,一般大于 len。

RedisObject

针对Long类型的优化:指针直接赋值为对应的值,节省空间

embstr编码方式:

字符串小于等于44字节时,RedisObject的数据是一块连续的内存空间。

raw编码方式

字符串大于等于44字节时,SDS会有独立的空间,用指针指向SDS结构

全局hash结构内存占用情况:

计算10字节图片用String存入redis的内存占用情况?

首先,由于id用的是Long类型,所以使用的是int编码,key和value各占16字节,结果是32字节

又由于全局hash表指向数据需要指针,key、value、next,又占用24字节

又由于分配内存时都是每8字节分配一次,即指针也占32字节

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

压缩列表

压缩列表能节省内存是因为它是用一系列连续的entry保存数据。

  • prev_len,表示前一个 entry 的长度。

prev_len 有两种取值情况:1 字节或 5 字节。取值 1 字节时,表示上一个 entry 的长度小于 254 字节。虽然 1 字节的值能表示的数值范围是 0 到 255,但是压缩列表中 zlend 的取值默认是 255,因此,就默认用 255 表示整个压缩列表的结束,其他表示长度的地方就不能再用 255 这个值了。所以,当上一个 entry 长度小于 254 字节时,prev_len 取值为 1 字节,否则,就取值为 5 字节。

  • len:表示自身长度,4字节;
  • encoding:表示编码方式,1字节;
  • content:保存实际数据;

指针会挨个放入内存中,无需额外指针指向,这样就可以节省指针所占用的空间

计算图片ID存储问题(优化版)

每个entry保存一个图片存储对象id(8字节),此时perv_len只需1字节,所以一个图片id存储对象Id所占空间大小是:14字节(1 + 4 + 1 + 8)。且采用集合类型时,一个key对应一个集合,能保存的数据多了很多,但也就用了一个dictEntry。

二级编码:把一个单值的数据拆分成两部分,前一部分作为hash结构的key,后一部分作为hash结构的value。

以图片 ID 1101000060 和图片存储对象 ID 3302000080 为例,我们可以把图片 ID 的前 7 位(1101000)作为 Hash 类型的键,把图片 ID 的最后 3 位(060)和图片存储对象 ID 分别作为 Hash 类型值中的 key 和 value

这样一条数据才占用16字节,相当于使用String类型的1/4

redis什么情况下使用压缩列表,什么情况下使用哈希表呢?

其实hash类型设置了用压缩列表保存数据的两个阈值,一旦超过阈值,Hash类型就会使用Hash表来保存数据。

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

超过其中一个就会导致使用哈希表

二级编码采用的长度有何讲究?

为了能充分使用压缩列表的精简内存布局,一般要控制保存在Hash集合中的元素个数。所以二级编码中,只用图片ID的后3位作为Hash集合的Key,也就保证了Hash集合个数不超过1000,同时把阈值hash-max-ziplist-entries设置为1000,这样Hash集合就可以一直使用压缩列表来节省内存空间。

总结

String内存的主要开销,RedisObject结构、SDS结构、dictEntry结构的内存开销。

可以使用压缩列表来保存数据,只需将单值数据拆分成两部分,分别作为Hash集合的key和value,即以二级编码的方式存入集合中。

二级编码类似分库,将主键多后三位作为分库的依据,后三位相同的主键会被映射到同一个哈希表中,再在这个哈希表内查询。第一层采用压缩列表的方式,降低了直接存储字符串单值数据的元数据冗余,第二层则采用保存具体的数据。这样两层的时间复杂度都是O1,但由于是两层查询,哈希速度和网络io如果不在服务端进行的话,时间最起码翻倍。这也相当于用时间换空间。平时可以使用压缩列表做一级表,二级哈希做主键,三级采用二叉树来做时间索引。这样主要是对主键做了两层映射。

彩蛋:可以使用以下网站来计算内存

Redis容量预估-极数云舟

问题

除了String类型和Hash类型,还有其他类型可以保存图片ID吗?

可以使用常规数组来存储,用二进制保存图片位置ID,多级压缩列表

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

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

相关文章

[杂谈]-电动汽车有哪些不同类型

电动汽车有哪些不同类型? 文章目录 电动汽车有哪些不同类型?1、概述2、纯电动汽车(BEV)3、燃料电池电动汽车(FCEV)4、插电式混合动力汽车 (PHEV)5、混合动力电动汽车 (HEV)6、轻度混合动力HEV7、…

树形DP()

没有上司的舞会 Ural 大学有 N 名职员,编号为 1∼N。 他们的关系就像一棵以校长为根的树,父节点就是子节点的直接上司。 每个职员有一个快乐指数,用整数 Hi 给出,其中 1≤i≤N。 现在要召开一场周年庆宴会,不过&am…

非结构化数据之XPath学习

1、XPath语法 XPath 是一门在 XML 文档中查找信息的语言。 XPath 可用来在 XML 文档中对元素和属性进行遍历。 <?xml version"1.0" encoding"ISO-8859-1"?> <bookstore> <book><title lang"eng">Harry Potter</t…

实战教程:如何将自己的Python包发布到PyPI上

1. PyPi的用途 Python中我们经常会用到第三方的包&#xff0c;默认情况下&#xff0c;用到的第三方工具包基本都是从Pypi.org里面下载。 我们举个栗子: 如果你希望用Python实现一个金融量化分析工具&#xff0c;目前比较好用的金融数据来源是 Yahoo 和 Google。你可能需要读取…

13-RocketMQ主从同步(HA实现)源码原理

slave每次接收到master发过来的一批commitlog数据时&#xff0c;会看master传过来的这段commitlog的起始端&#xff0c;对应的全局物理偏移量&#xff0c;和slave本地存储的批commitlog数据的最大物理偏移量&#xff0c;是否相等 如果相等&#xff0c;也说明master端没有给sla…

TCP详解之三次握手和四次挥手

TCP详解之三次握手和四次挥手 1. TCP基本认识 1.1 什么是 TCP TCP是面向连接的、可靠的、基于字节流的传输层通信协议。 1.2 TCP协议段格式 我们先来看看TCP首部协议的格式 我们先来介绍一些与本文关联比较大的字段&#xff0c;其他字段不做详细阐述。 序列号&#xff1a…

【javaweb课设源码】图书管理系统SSM Mysql 期末课设

文章目录 简介 简介 本系统使用Javaweb技术制作&#xff0c;数据库为mysql 附带论文报告文档 printf("需要源码&#xff0c;可以baidu学长敲代码")&#xff1b;

input子系统框架、外设驱动开发

一、input子系统基本框架 Linux内核为了两个目的&#xff1a; 简化纯输入类外设&#xff08;如&#xff1a;键盘、鼠标、游戏杆、轨迹球、触摸屏。。。等等&#xff09;的驱动开发统一输入类外设产生的数据格式&#xff08;struct input_event&#xff09;&#xff0c;更加方…

【LeetCode题目详解】第九章 动态规划part10 121. 买卖股票的最佳时机 122.买卖股票的最佳时机II (day49补)

本文章代码以c为例&#xff01; 股票问题是一个动态规划的系列问题 一、力扣第121题&#xff1a;买卖股票的最佳时机 题目&#xff1a; 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#x…

Android学习之路(14) AMS与PMS详解

Android 系统启动流程与 Zygote、SystemServer 在讲解 Zygote 之前&#xff0c;考虑到不同的系统版本源码都不相同&#xff0c;以下分析的源码基于 Android 8.0.0。 init 进程 当系统启动时&#xff0c;init 进程是继 Linux 内核启动后第二个启动的进程&#xff0c;它是在用…

AOP代理中Cglib使用场景

有接口时会使用JDK动态代理 没有接口实现类的情况下使用Cglib进行动态代理

layui手机端使用laydate时间选择器被输入法遮挡的解决方案

在HTML中&#xff0c;你可以使用input元素的readonly属性来禁止用户输入&#xff0c;但是这将完全禁用输入&#xff0c;而不仅仅是禁止弹出输入法。如果你想允许用户在特定条件下输入&#xff0c;你可以使用JavaScript来动态地切换readonly属性。 readonly属性 增加readonly属…

【iOS】MVC

文章目录 前言一、MVC各层职责1.1、controller层1.2、model层1.3、view层 二、总结三、优缺点3.1、优点3.2、缺点 四、代码示例 前言 MVC模式的目的是实现一种动态的程序设计&#xff0c;使后续对程序的修改和扩展简化&#xff0c;并且使程序某一部分的重复利用成为可能。除此…

【交叉熵损失torch.nn.CrossEntropyLoss详解-附代码实现】

CrossEntropyLoss 什么是交叉熵softmax损失计算验证CrossEntropyLoss 输入输出介绍验证代码 什么是交叉熵 交叉熵有很多文章介绍&#xff0c;此处不赘述。只需要知道它是可以衡量真实值和预测值之间的差距的&#xff0c;因而用交叉熵来计算损失的时候&#xff0c;损失是越小越…

【JavaScript手撕代码】new

目录 手写 手写 /* * param {Function} fn 构造函数 * return {*} **/ function myNew(fn, ...args){if(typeof fn ! function){return new TypeError(fn must be a function)}// 先创建一个对象let obj Object.create(fn.prototype)// 通过apply让this指向obj, 并调用执行构…

SHIB去零计划:创新金融未来,打造稳定数字资产新范式

SHIB去零计划&#xff0c;由星火有限公司发起&#xff0c;以区块链去中心化手段解决信任危机&#xff0c;对抗垄断与不公平问题&#xff0c;破解经济制裁&#xff0c;实现稳定数字资产的快速有效、平等互利交易。星火有限公司&#xff0c;一家跨国运营集团&#xff0c;主营业务…

UIStackView入门使用两个问题

项目中横向一排元素&#xff0c;竖向一排元素&#xff0c;可以使用UIStackView。UIStackView的原理不做介绍&#xff0c;这里主要讲两个初次使用容易出现的两个问题。 首先创建一个stackview -(UIStackView*)titleStackView{if(_titleStackView nil){_titleStackView [UISta…

时序分解 | MATLAB实现北方苍鹰优化算法NGO优化VMD信号分量可视化

时序分解 | MATLAB实现北方苍鹰优化算法NGO优化VMD信号分量可视化 目录 时序分解 | MATLAB实现北方苍鹰优化算法NGO优化VMD信号分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 北方苍鹰优化算法NGO优化VMD&#xff0c;对其分解层数&#xff0c;惩罚因子数做优化…

绝对的搜索利器

苏生不惑第450 篇原创文章&#xff0c;将本公众号设为星标&#xff0c;第一时间看最新文章。 今天分享几个文件搜索利器&#xff0c;下载地址在公众号苏生不惑后台回复2023909&#xff0c;你的小电影要藏不住了。 首先自然是Everything https://www.voidtools.com/zh-cn/&#…

python DVWAXSSPOC练习

XSS反射性低难度 数据包 GET /dv/vulnerabilities/xss_r/?name%3Cscript%3Ealert%28%27xss%27%29%3C%2Fscript%3E HTTP/1.1Host: 10.9.75.161Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Ch…