Redis的内存回收和对象共享

Redis中的内存回收

因为 C 语言并不具备自动的内存回收 功能, 所以Redis在自己的对象系统中构建了一个引用计数 技术实现的内存回收机制, 通过这一机制, 程序可以通过跟踪对象的引用计数信息 , 在适当的时候自动释放对象并进行内存回收。

每个对象的引用计数 信息由 redisObject 结构的 refcount 属性记录:

c 复制代码
typedef struct redisObject {

    // ...

    // 引用计数
    int refcount;

    // ...

} robj;

对象的引用计数信息 会随着对象的使用状态而不断变化:

  • 在创建一个新对象时, 引用计数的值会被初始化为 1 ;
  • 当对象被一个新程序使用时, 它的引用计数值会被增一;
  • 当对象不再被一个程序使用时, 它的引用计数值会被减一;
  • 当对象的引用计数值变为 0 时, 对象所占用的内存会被释放。
函数 作用
incrRefCount 将对象的引用计数值增一。
decrRefCount 将对象的引用计数值减一, 当对象的引用计数值等于 0 时, 释放对象。
resetRefCount 将对象的引用计数值设置为 0 , 但并不释放对象, 这个函数通常在需要重新设置对象的引用计数值时使用。

对象的生命周期

对象的整个生命周期可以划分为创建对象 、操作对象 、释放对象三个阶段。

c 复制代码
// 创建一个字符串对象 s ,对象的引用计数为 1
robj *s = createStringObject(...)

// 对象 s 执行各种操作 ...

// 将对象 s 的引用计数减一,使得对象的引用计数变为 0
// 导致对象 s 被释放
decrRefCount(s)

对象共享

对象的引用除了进行内存回收 之外,还带有对象共享的作用。

假设键A创建一个包含整数值100的字符串作为值对象

现在假设键B也要创建一个同样的字符串作为值对象,有两种做法:

  1. 为键 B 新创建一个包含整数值 100 的字符串对象;
  2. 让键 A 和键 B 共享同一个字符串对象;

第二种方法是明显优于第一种方法的。

在Redis中, 让多个键共享同一个值对象需要执行以下两个步骤:

  1. 将数据库键的值指针指向一个现有的值对象;
  2. 将被共享的值对象的引用计数增一。

共享对象机制对于节约内存非常有帮助, 数据库中保存的相同值对象越多, 对象共享机制就能节约越多的内存。

Redis会在初始化服务器时, 创建一万个字符串对象, 这些对象包含了从 0 到 9999 的所有整数值, 当服务器需要用到值为 0到 9999 的字符串对象时, 服务器就会使用这些共享对象, 而不是新创建对象。

当服务器考虑将一个共享对象设置为键的值对象时, 程序需要先检查给定的共享对象和键想创建的目标对象是否完全相同 , 只有在共享对象和目标对象完全相同的情况下, 程序才会将共享对象用作键的值对象, 而一个共享对象保存的值越复杂 , 验证共享对象和目标对象是否相同所需的复杂度就会越高 , 消耗的 CPU时间也会越多:

  • 如果共享对象是保存整数值 的字符串对象, 那么验证操作的复杂度为 ;
  • 如果共享对象是保存字符串值 的字符串对象, 那么验证操作的复杂度为 ;
  • 如果共享对象是包含了多个值(或者对象的)对象, 比如列表对象或者哈希对象, 那么验证操作的复杂度将会是 。

因此, 尽管共享更复杂的对象可以节约更多的内存, 但受到CPU时间的限制,Redis 只对包含整数值的字符串对象进行共享。

相关推荐
打工仔折腾 AI17 分钟前
LLaMA 1 到 LLaMA 3 架构演进拆解:从 RoPE、GQA 到词表扩张
人工智能·后端·python·深度学习·langchain·llama
可乐鸡翅yeah_34 分钟前
HLS 分片过期清理,直播旧 TS 分片磁盘爆满问题处理
java·后端·spring·m3u8·m3u8在线·音视频在线播放
张彦峰ZYF1 小时前
加了锁不等于扛得住争用:synchronized、显式锁与 CAS 的语义分层、争用代价账本与选型判据
后端·同步设施·内置锁的四种状态与单向升级·可重入的由来与四条硬边界·显式锁的状态字段与等待队列·读写锁与邮戳锁·一次同步的开销账本
专业程序开发源1 小时前
SSM校园拍摄交流服务平台36936-计算机课程设计、毕业设计
java·spring boot·后端·python·elasticsearch·php·课程设计
Gopher_HBo1 小时前
zap采样器与性能优化内幕
后端
变量探索SEQVEC1 小时前
我埋了 8 个假文件,看谁会上钩:12 天 502 次扫描实录
后端
llqbzllll1 小时前
HashMap 的核心结构:从一次 put 看到扩容、桶迁移与树化边界
后端
晚安code1 小时前
设计模式入门:吃透 SOLID 原则与迪米特法则,再学 5 个高频模式
后端·设计模式
樱花落木兰1 小时前
分布式登录实战:Session 会话共享改造,Redis 存储用户登录状态
java·javascript·数据库·redis·分布式·缓存
ShineWinsu2 小时前
对于Redis:Steam、Geospatial、Hyperloglog、Bitmap、Bitfield类型的解析
数据库·c++·redis·分布式·缓存·面试·zset