前面我们看了Redis用到的主要数据结构,如简单动态字符串(SDS)、双向链表、字典、压缩列表、整数集合等。

但是Redis并没有直接使用这些数据结构来实现键值对,而是基于这些数据结构创建了一个对象系统,这个系统包括字符串对象、列表对象、哈希对象、集合对象、有序集合对象,除此之外,redis的对象系统还实现了基于计数技术的内存回收机制,另外redis还通过引用计数技术实现了对象共享机制(适当条件下,多个数据库键共享同一个对象来节约内存)。

最后,redis的对象带有访问时间记录信息,该信息可以用于计算数据库键的空转时长,在服务器启用了maxmemory功能的情况下,空转时长较大的键会优先被服务器删除。

1、Redis中的每个结构都是由redisObject结构标识,包含ptr(指向底层实现的数据结构)、encoding(决定用那种底层数据结构)、type等属性。

2、当我们创建一个键值对时,我们至少会创建两个对象:键对象(字符串对象),值对象(物种类型)。

3、字符串对象的编码可以是整数、raw或者enbstr、sds

  1. enbstr(短字符串长度小于32)调用一次分配内存函数,分配一个连续的内存包含redisObject结构与sdshdr结构,不包含修改命令,执行任何修改命令会转为raw对象。

  2. sds(字符串长度超过32)。

  3. raw 会调用两次内存分配分别创建redisObject结构与sdshdr结构。

4、列表对象,列表对象的编码可以是ziplist或者linkedlist

  1. ziplist使用压缩列表作为底层实现。列表对象保存的所有字符串元素长度都小于64字节,元素数量小于512个时使用压缩列表做为底层实现。

  2. linkedlist编码列表对象使用双向链表作为底层实现,每个双向链表节点都保存一个字符串对象。

5、哈希对象

  1. 哈希对象的编码可以是ziplist或者hashtable

  2. ziplist编码的哈希对象使用压缩表作为底层实现,当由新的键值对加入到hash对象时,程序会先将保存了键的压缩列表节点推入到压缩列表的表尾,然后将保存了值的压缩列表节点推入到压缩列表的表尾。

  3. 使用hashtable作为编码的哈希对象使用字典作为底层实现,键使用字符串对象,值使用字符串对象。

6、集合对象

  1. 集合对象的编码可以是 intset或者是hashtable

  2. intset编码的集合对象使用整数集合作为底层实现。

  3. hashtable编码的集合对象使用字典作为底层实现,字典的每个键都是一个字符串对象,每个字符串对象包含一个集合元素,而字段的值则全部设置为null。

  4. 对象转换 。intset转hashtable条件:元素中不全是整数或者元素数量超过512.

7、有序集合对象

  1. 有序集合的编码可以是ziplist 或者skiplist

  2. ziplist编码的压缩列表对象使用压缩列表作为底层实现,每个集合元素使用两个挨在一起的压缩列表节点来保存,第一个节点保存元素的成员(member)第二个元素则保存元素的分值(score)。

  3. skiplist编码的有序集合对象使用zset结构作为底层实现,一个zset结构同时包含一个字典和一个跳跃表。

  4. typedef struct zset{
    zskiplist *zsl;
    dict *dict;//保存从成员到分值的映射,键保存元素成员 值保存了分数。
    }
  5. 解释下为什么同时使用字典与跳跃表来实现有序集合:虽然用两种结构的任意一种都能实现有序集合,但是当我们只是用字典来实现有序集合时,由于字典是一个无序的保存元素,当我们实行范围操作时,需要先对所有的元素进行排序,这里所使用的时间复杂度至少为O(NlogN),并且有额外的内存消费;另外如果只使用跳跃表来实现有序集合时,虽然范围操作的优势被保留,但是没有了字典根据成员查找分值时这一操作的复杂度将从O(1)提升到O(logN)。

  6. 编码转换,当元素的数量小于128,且每个元素的长度都小于64字节时,使用ziplist。

8、内存回收

  1. 每个对象的引用技术信息由redisObject结构的refcount属性记录。

  2. 创建对象时,计数值会被默认初始化为1,被程序使用时,计数器加一,不再被使用时,计数器减一,当计数器为0时,对象占用的内存会被释放。

9、对象空转时长

  1. 对象空转时长使用redisObjet结构中的lru属性记录,该属性记录对象最后一次被访问的时间。

--------- end --------

每天学一点,总会有收获。

说明:尊重作者知识产权,文中内容参考《Redis设计与实现》,仅在此做学习与大家分享。

Redis学习笔记(六) 对象的更多相关文章

  1. Redis学习笔记六:持久化实验(AOF,RDB)

    作者:Grey 原文地址:Redis学习笔记六:持久化实验(AOF,RDB) Redis几种持久化方案介绍和对比 AOF方式:https://blog.csdn.net/ctwctw/article/ ...

  2. Redis学习笔记六:独立功能之 Lua 脚本

    Redis 2.6 开始支持 Lua 脚本,通过在服务器环境嵌入 Lua 环境,Redis 客户端中可以原子地执行多个 Redis 命令. 使用 eval 命令可以直接对输入的脚本求值: 127.0. ...

  3. Redis学习笔记一:数据结构与对象

    1. String(SDS) Redis使用自定义的一种字符串结构SDS来作为字符串的表示. 127.0.0.1:6379> set name liushijie OK 在如上操作中,name( ...

  4. Redis学习笔记(二) Redis 数据类型

    Redis 支持五种数据类型:string(字符串).list(列表).hash(哈希).set(集合)和 zset(有序集合),接下来我们讲解分别讲解一下这五种类型的的使用. String(字符串) ...

  5. redis 学习笔记(6)-cluster集群搭建

    上次写redis的学习笔记还是2014年,一转眼已经快2年过去了,在段时间里,redis最大的变化之一就是cluster功能的正式发布,以前要搞redis集群,得借助一致性hash来自己搞shardi ...

  6. (转)redis 学习笔记(1)-编译、启动、停止

    redis 学习笔记(1)-编译.启动.停止   一.下载.编译 redis是以源码方式发行的,先下载源码,然后在linux下编译 1.1 http://www.redis.io/download 先 ...

  7. java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

    java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...

  8. Redis学习笔记(二)Redis支持的5种数据类型的总结之String和Hash

    引言 在Redis学习笔记(一)中我们已经会安装并且简单使用Redis了,接下来我们一起来学习下Redis支持的5大数据类型. 简介 Redis是REmote DIctionary Server(远程 ...

  9. Redis学习笔记(2)——Redis的下载安装部署

    一.下载Redis Redis的官网下载页上有各种各样的版本,如图 但是官网下载的Redis项目不正式支持Windows.如果需要再windows系统上部署,要去GitHub上下载.我下载的是Redi ...

  10. Redis学习笔记二 (BitMap算法分析与BitCount语法)

    Redis学习笔记二 一.BitMap是什么 就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身.我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省 ...

随机推荐

  1. Java数组模拟环形队列

    2.环形队列 (上一篇队列:https://www.cnblogs.com/yxm2020/p/12676323.html) 百度百科 1.假溢出 ​ 系统作为队列用的存储区还没有满,但队列却发生了溢 ...

  2. Spring Boot 中使用自定义注解,AOP 切面打印出入参日志及Dubbo链路追踪透传traceId

    一.使用背景 开发排查系统问题用得最多的手段就是查看系统日志,在分布式环境中一般使用 ELK 来统一收集日志,但是在并发大时使用日志定位问题还是比较麻烦,由于大量的其他用户/其他线程的日志也一起输出穿 ...

  3. centos7 —— 网络连接问题

    今天用虚拟机(VM)安装好centos7后,发现无法连接网络,百思不得其解: 第一步:找到需要修改的文件位置,查明原因 #.查看网络是否可以ping通 ~ ping www.baidu.com #.查 ...

  4. Springboot:员工管理之公共页面提取 高亮显示(十(5))

    把顶部和左侧的公共代码分别放到header.html和left.html中 顶部代码:resources\templates\header.html 主内容展示: <!DOCTYPE html& ...

  5. pytorch中的前项计算和反向传播

    前项计算1 import torch # (3*(x+2)^2)/4 #grad_fn 保留计算的过程 x = torch.ones([2,2],requires_grad=True) print(x ...

  6. 算法笔记刷题2(codeup 1928)

    又磕了一晚上,多点测试真的很烦 ,完全不知道错哪里,后来发现是我变量名命名不规范导致自己晕了填错了,其实思路还是对的 我觉得书上的做法也还行,但我不太喜欢用二维数组,所以拿以前写的算天数的程序改装了一 ...

  7. 9个小技巧让你的 if else看起来更优雅

    if else 是我们写代码时,使用频率最高的关键词之一,然而有时过多的 if else 会让我们感到脑壳疼,例如下面这个伪代码: 是不是很奔溃?虽然他是伪代码,并且看起来也很夸张,但在现实中,当我们 ...

  8. ERROR 2003 (HY000): Can't connect to MySQL server on '192.168.33.10' (111) 解决方法

    谷歌了一下之后,原来是在mysql的my.cnf中有下面一段代码: # Instead of skip-networking the default is now to listen only on ...

  9. 在java 8 stream表达式中实现if/else逻辑

    目录 简介 传统写法 使用filter 总结 简介 在Stream处理中,我们通常会遇到if/else的判断情况,对于这样的问题我们怎么处理呢? 还记得我们在上一篇文章lambda最佳实践中提到,la ...

  10. Spring Cloud 系列之 Stream 消息驱动(二)

    本篇文章为系列文章,未读第一集的同学请猛戳这里:Spring Cloud 系列之 Stream 消息驱动(一) 本篇文章讲解 Stream 如何实现消息分组和消息分区. 消息分组 如果有多个消息消费者 ...