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

redis中的set

Redis 的 SET 数据结构根据集合的大小和元素类型动态选择底层实现方式:

  • 整数集合(IntSet):当集合中的所有元素都是整数且集合大小较小时,使用整数集合以节省内存。
  • 哈希表(HashTable):当集合中包含非整数元素或集合大小较大时,使用哈希表以支持高效的动态操作。
    键值对存储:哈希表使用键值对的方式存储集合中的元素,其中键是集合中的元素,值是一个固定值(如 NULL)。

Redis中的set和java中的set集合有相似之处,它的元素不会按照插入的先后顺序而存储,且元素是不允许重复的。set内部使用到了intset(整数集合)和hashtable(哈希表)两种方式来存储元素,如果set存储的元素是整数,且当元素个数小于512个会选择intset存储,目的是减少内存空间,遇到两种情况会发生变化,
就是当存储的元素个数达到512(通过set-max-intset-entries 配置)
或者添加了非整数值时如:‘b’,set会选择hashtable作为存储结构

整数集合intset

整数集合intset是用来存储整数的集合,且存储是按照小到大的顺序来存储(可以二分查找),intset目的是用来节省内存,
当Redis集合类型的元素都是整数并且都处在64位有符号整数范围之内时,使用该结构体存储,我们看一下它的结构:查看源码
在这里插入图片描述
在这里插入图片描述

解释:

length: contents中元素的个数
contents:存储元素的数组,需要根据encoding来决定多少个字节表示一个元素
encoding: 编码类型,决定每个元素占用几个字节,有三种类型
在这里插入图片描述

虽然intset结构将contents属性声明为int8_t类型的数组,但实际上contents数组并不保存任何int8_t类型的值,contents数组的真正类型取决于encoding属性的值:
如果encoding属性的值为INTSET_ENC_INT16,那么contents就是一个int16_t类型的数组,数组里的每个项都是一个int16_t类型的整数值(最小值为-32768,最大值为32767 )
如果encoding属性的值为INTSET_ENC_INT32,那么contents就是一个int32_t类型的数组,数组里的每个项都是一个int32_t类型的整数值(最小值为-2147483648,最大值为2147483647 )
如果encoding属性的值为INTSET_ENC_INT64,那么contents就是一个int64_t类型的数组,数组里的每个项都是一个int64_t类型的整数值(最小值为-9223372036854775808,最大值为9223372036854775807)
intset会根据插入的值判断是否扩容,根据插入内容来修改encoding使用什么类型,从而决定contents每个元素的字节数,紧跟着对contents进行扩容。

intset的升级

IntSet 的升级机制

1. 触发条件
当尝试向 intset 中插入一个新元素,而该元素的类型超出了当前 intset 的编码范围时,会触发升级操作。例如:

  • 如果当前 intset 的编码是 INTSET_ENC_INT16(2 字节整数),而新插入的元素值为 65536(需要 32 位整数表示),则会触发升级。

2. 升级过程
升级过程主要包括以下步骤:
1.确定新编码:根据新元素的大小,确定新的编码方式(如从 INTSET_ENC_INT16 升级到 INTSET_ENC_INT32)。
2.分配新空间:根据新的编码方式和当前元素数量(包括新元素),分配新的内存空间。
3.复制和转换现有元素:将现有元素从旧编码转换为新编码,并按顺序复制到新的内存空间。
4.插入新元素:将新元素插入到合适的位置,保持 intset 的有序性。
5.更新元数据:更新 intset 的 encoding 属性为新的编码方式,并递增 length 属性。

3. 示例

假设有一个 intset,当前编码为 INTSET_ENC_INT16,包含元素 {5, 10, 20}。现在尝试插入元素 50000,该值超出了 int16_t 的范围(-32768 到 32767),因此需要升级:

  • 升级编码为 INTSET_ENC_INT32,每个整数占用 4 字节。
  • 分配新的内存空间,大小为 4 * (3 + 1) 字节(现有 3 个元素,加上新元素)。
  • 将现有元素 {5, 10, 20} 转换为 32 位整数,并按顺序复制到新的内存空间。
  • 插入新元素 50000 到数组末尾。
  • 更新 encoding 为 INTSET_ENC_INT32,并将 length 增加到 4。

4. 不支持降级

一旦 intset 升级到更大的编码方式,就不会再降级。即使后续删除了导致升级的元素,也不会将编码方式降回原来的较小类型。这是因为降级操作可能会带来额外的性能开销,而且 Redis 设计上倾向于避免频繁的结构转换。

5. 性能和内存优化

  • 性能:升级操作虽然涉及内存分配和数据复制,但由于 intset 通常用于存储小集合,因此整体性能影响较小。
  • 内存优化:通过动态升级,intset 能够在不同阶段选择最合适的编码方式,从而节省内存。

总结

Redis 的 intset 升级机制是一种灵活且高效的内存管理策略,能够在插入超出当前编码范围的元素时自动调整编码方式,确保数据结构的紧凑性和操作的高效性。

相关文章:

  • pikachu靶场搭建教程,csfr实操
  • AI日报 - 2025年4月8日
  • 关于动态规划
  • 解决 Lettuce 在 Redis 集群模式下的故障转移问题
  • 基于人工智能的医学影像关联分析:利用潜在空间几何混杂因素校正法|文献速递-深度学习医疗AI最新文献
  • WEB安全--内网渗透--利用Net-NTLMv2 Hash
  • 使用Scade实现神经网络算法
  • CMake 字段使用
  • 蓝桥杯真题--最长子序列 and 2023
  • SQL:Primary Key(主键)和Foreign Key(外键)
  • cpp自学 day20(文件操作)
  • 关于sqlsugar实体多层List映射的问题
  • 第十五届蓝桥杯大赛软件赛省赛Python 大学 C 组题目试做(中)【本期题目:回文数组,挖矿】
  • CmLicense授权损耗规避措施
  • spring boot 实现spring mvc过程中WebMvcConfigurer接口及其相关实现类的详细对比
  • Redis 的五种数据类型面试回答
  • 安全编码课程 实验6 整数安全
  • WPF依赖注入
  • 【金仓数据库】
  • 深入解析 MySQL 中的日期时间函数:DATE_FORMAT 与时间查询优化
  • 有哪个网站可以做口腔执业助理医师题库/百度大数据搜索引擎
  • 网站首页制作怎么做的/广告联盟app下载赚钱
  • 英文网站怎么设置中文/湖南长沙今日疫情
  • 个人网页设计html加js代码/seo网站推广专员
  • 有哪些做婚品的网站/营销系统
  • 阳江招聘网的拼音/seo推广软件