学习总结录 学习总结录
首页
归档
分类
标签
  • Java基础
  • Java集合
  • MySQL
  • Redis
  • JVM
  • 多线程
  • 计算机网络
  • 操作系统
  • Spring
  • Kafka
  • Elasticsearch
  • Python
  • 面试专题
  • 案例实践
  • 工具使用
  • 项目搭建
  • 服务治理
  • ORM框架
  • 分布式组件
  • MiniSpring
  • 设计模式
  • 算法思想
  • 编码规范
友链
关于
GitHub (opens new window)
首页
归档
分类
标签
  • Java基础
  • Java集合
  • MySQL
  • Redis
  • JVM
  • 多线程
  • 计算机网络
  • 操作系统
  • Spring
  • Kafka
  • Elasticsearch
  • Python
  • 面试专题
  • 案例实践
  • 工具使用
  • 项目搭建
  • 服务治理
  • ORM框架
  • 分布式组件
  • MiniSpring
  • 设计模式
  • 算法思想
  • 编码规范
友链
关于
GitHub (opens new window)
  • Java基础

  • Java集合

  • MySQL

  • Redis

    • Redis核心技术01-基础数据结构
    • Redis核心技术02-线程IO模型
    • Redis核心技术03-持久化
    • Redis核心技术04-数据同步
    • Redis核心技术05-哨兵机制
    • Redis核心技术06-哨兵集群
    • Redis核心技术07-切片集群
    • Redis核心技术08-String
      • Redis核心技术08-String
        • 内存开销
        • 元数据开销
        • RedisObject开销
        • jemalloc开销
        • 节省内存
      • 集合类型保存单值的键值对
      • 参考
    • Redis核心技术09-keys统计案例与方案
    • Redis核心技术10-GEO
    • Redis核心技术11-时间序列数据存储
    • Redis核心技术12-消息队列
    • Redis核心技术13-异步机制
    • Redis核心技术14-CPU结构对Redis性能影响
    • Redis核心技术15-应对变慢的Redis
    • Redis核心技术16-删除数据后内存占用率还是很高
    • Redis核心技术17-缓冲区
    • Redis核心技术18-Redis缓冲是如何工作的
    • Redis核心技术19-缓冲替换策略
    • Redis核心技术20-缓冲异常
    • Redis核心技术21-缓存污染
    • Redis核心技术22-无锁原子操作
    • Redis核心技术23-分布式锁
    • Redis核心技术24-事务机制
    • Redis核心技术25-主从同步与故障切换的坑
    • Redis核心技术26-脑裂问题
    • Redis核心技术27-Redis在秒杀场景的关键技术
  • JVM

  • 多线程

  • 计算机网络

  • Spring

  • Kafka

  • Elasticsearch

  • Python

  • 面试专题

  • 知识库
  • Redis
旭日
2023-03-31
目录

Redis核心技术08-String

# Redis核心技术08-String

# 内存开销

# 元数据开销

除了记录实际数据,String类型还需要额外的内存空间记录数据长度、空间使用等信息,这些信息也叫做元数据。如果本身数据很小,元数据的空间开销就会显得比较大。

String类型保持数据如下:

  • 保存 64 位有符号整数时,String 类型会把它保存为一个 8 字节的 Long 类型整数。

  • 保存的数据中包含字符时,String 类型就会用简单动态字符串(Simple Dynamic String,SDS)结构体来保存。

    image-20220811092407542

    • buf:字节数组,保存实际数据。为了表示字节数组的结束,Redis 会自动在数组最后加一个“\0”,这就会额外占用 1 个字节的开销。
    • len:占 4 个字节,表示 buf 的已用长度。
    • alloc:占个 4 字节,表示 buf 的实际分配长度,一般大于 len。

    在SDS中,buf保存实际数据,而len和alloc本身其实是SDS结构体的额外开销。

    另外,除了 SDS 的额外开销,还有一个来自于 RedisObject 结构体的开销。一个 RedisObject 包含了 8 字节的元数据和一个 8 字节指针,这个指针再进一步指向具体数据类型的实际数据所在。

    image-20220811093633481

# RedisObject开销

  • 当保存的是 Long 类型整数时,RedisObject 中的指针就直接赋值为整数数据了,这样就不用额外的指针再指向整数了,节省了指针的空间开销。
  • 当保存的是字符串数据,并且字符串小于等于 44 字节时,RedisObject 中的元数据、指针和 SDS 是一块连续的内存区域,这样就可以避免内存碎片。这种布局方式也被称为 embstr 编码方式。
  • 当字符串大于 44 字节时,SDS 的数据量就开始变多了,Redis 就不再把 SDS 和 RedisObject 布局在一起了,而是会给 SDS 分配独立的空间,并用指针指向 SDS 结构。这种布局方式被称为 raw 编码模式。

image-20220811093724914

# jemalloc开销

Redis会使用一个全局哈希表保存所有键值对,哈希表的每一项是一个 dictEntry 的结构体,用来指向一个键值对。dictEntry 结构中有三个 8 字节的指针,分别指向 key、value 以及下一个 dictEntry,三个指针共 24 字节。

image-20220811094846602

jemalloc 在分配内存时,会根据我们申请的字节数 N,找一个比 N 大,但是最接近 N 的 2 的幂次数作为分配的空间,这样可以减少频繁分配的次数。

如果你申请 6 字节空间,jemalloc 实际会分配 8 字节空间;如果你申请 24 字节空间,jemalloc 则会分配 32 字节

# 节省内存

压缩列表的构成:表头有三个字段 zlbytes、zltail 和 zllen,分别表示列表长度、列表尾的偏移量,以及列表中的 entry 个数。压缩列表尾还有一个 zlend,表示列表结束。

image-20220811100255758

压缩列表之所以能节省内存,就在于它是用一系列连续的 entry 保存数据。每个entry的元数据包括下面几个部分:

  • prev_len: 表示前一个 entry 的长度。prev_len 有两种取值情况:1 字节或 5 字节。取值 1 字节时,表示上一个 entry 的长度小于 254 字节。反之,就取值为 5 字节。
  • len:表示自身长度,4字节。
  • encoding:表示编码方式,1 字节;
  • content:保存实际数据。

但是这种方案存在一个问题,那就是集合类型保存键值对时,一个键对应了一个集合的数据,而我们需要使用这种集合类型来保存单值键值对。

# 集合类型保存单值的键值对

在保存单值的键值对时,可以采用基于 Hash 类型的二级编码方法。这里说的二级编码,就是把一个单值的数据拆分成两部分,前一部分作为 Hash 集合的 key,后一部分作为 Hash 集合的 value,这样一来,我们就可以把单值数据保存到 Hash 集合中了。

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

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

所以我们要控制好二级编码方法中采用的 ID 长度。一旦从压缩列表转为了哈希表,Hash 类型就会一直用哈希表进行保存,而不会再转回压缩列表了。

# 参考

Redis核心技术与实战 (opens new window)

#Redis
上次更新: 2024/06/29, 15:13:44
Redis核心技术07-切片集群
Redis核心技术09-keys统计案例与方案

← Redis核心技术07-切片集群 Redis核心技术09-keys统计案例与方案→

最近更新
01
基础概念
10-31
02
Pytorch
10-30
03
Numpy
10-30
更多文章>
Theme by Vdoing | Copyright © 2021-2024 旭日 | 蜀ICP备2021000788号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式