Redis数据结构之集合对象

  • Redis对象
  • 集合对象
    • intset编码
    • hashtable编码

Redis对象

在了解Redis数据结构的时候我们会学习到简单动态字符串,压缩链表等。
但Redis并没有直接使用这些数据结构来实现键值对数据库,而是基于这些数据结构创建了一个对象系统,这个系统包含字符串对象、列表对象、哈希对象、集合对象和有序集合对象这五种类型的对象。Redis使用对象表示键和值,每次新建一个键值对时,我们就创建了两个对象。

集合对象

intset编码

创建一个intset编码的集合对象

127.0.0.1:6379> sadd nums 1 2 3 5
(integer) 4
127.0.0.1:6379>
127.0.0.1:6379> type nums
set
127.0.0.1:6379> object encoding nums
"intset"

所有元素都被直接包含在一个整数集合里

hashtable编码

当传入字符时,变为hashtable编码

127.0.0.1:6379> sadd nums "hello"
(integer) 1
127.0.0.1:6379> object encoding nums
"hashtable"

hashtable编码的集合对象底层由字典实现。字典的键就是集合的内容,值为null。


Redis字典的底层实现

redis字典所使用的hash表结构

typedef struct dictht {    // 哈希表数组    dictEntry **table;    // 哈希表大小    unsigned long size;    //哈希表大小掩码,用于计算索引值    //总是等于size-1    unsigned long sizemask;    // 该哈希表已有节点的数量    unsigned long used;
} dictht;

table属性是一个数组,数组中的每个元素都是一个指向dictEntry结构的指针,每个dictEntry结构保存着一个键值对。size属性记录了哈希表的大小,也即是table数组的大小,而used属性则记录了哈希表目前已有节点(键值对)的数量。sizemask属性的值总是等于size-1,这个属性和哈希值一起决定一个键应该被放到table数组的哪个索引上面。

一个空的hash表

dictEntry*[4]是一个数组,数组里的每一元素都指向一个dictEntry结构,dictEntry包含3个属性,key,value,发生散列冲突时指向下一个节点的指针next。结构如下,看得出是使用链地址法解决散列冲突。


redis的字典是通过hash表来实现的

redis字典结构

typedef struct dict {    // 类型特定函数    dictType *type;    // 私有数据    void *privdata;   // 哈希表    dictht ht[2];    // rehash索引    //当rehash不在进行时,值为-1    in trehashidx; /* rehashing not in progress if rehashidx == -1 */} dict;

type属性和privdata属性是针对不同类型的键值对,为创建多态字典而设置的:·type属性是一个指向dictType结构的指针,每个dictType结构保存了一簇用于操作特定类型键值对的函数,Redis会为用途不同的字典设置不同的类型特定函数。·而privdata属性则保存了需要传给那些类型特定函数的可选参数。

而redis字典保存两个hash表,当我们新建一个redis字典时,默认使用ht[0] hash表,结构如下


redis字典为什么要维护两个hash表?

redis字典为了控制创建的hash表的空间开销,redis会动态调整hash表的空间大小,当ht[0]的长度满了,这里的ht[0]满了并不是指dictEntry数组里面每一个元素都存储了一个dictEntry,而是dictht的used和size相同,可能有部分dictEntry会发生散列冲突的。
此时再向字典添加元素,此时redis字典就会进行扩容。
首先对ht[1进行扩容,扩容的大小为比当前当前容量大的2的n次方,目标大小必须为2的n次方,这样系统进行内存分配的效率才有保证,比如当前容量ht[0]的容量为4,那么扩容的大小就应该为2的3次方也就是8.再将ht[0]的内容迁移到ht[1]此时redis字典的结构如下

这样就可以减少hash表的内存占用,不够的时候就扩容hash表。这种方法虽然节约了内存,但如果hash表已经很长了的时候,此时再扩容它的内存再分配的规模可能就会很大,造成性能影响。因此,为了避免rehash对服务器性能造成影响,服务器不是一次性将ht[0]里面的所有键值对全部rehash到ht[1],而是分多次、渐进式地将ht[0]里面的键值对慢慢地rehash到ht[1]。
以下是哈希表渐进式rehash的详细步骤:
1)为ht[1]分配空间,让字典同时持有ht[0]和ht[1]两个哈希表。
2)在字典中维持一个索引计数器变量rehashidx,并将它的值设置为0,表示rehash工作正式开始。
3)在rehash进行期间,每次对字典执行添加、删除、查找或者更新操作时,程序除了执行指定的操作以外,还会顺带将ht[0]哈希表在rehashidx索引上的所有键值对rehash到ht[1],当rehash工作完成之后,程序将rehashidx属性的加一。
4)随着字典操作的不断执行,最终在某个时间点上,ht[0]的所有键值对都会被rehash至ht[1],这时程序将rehashidx属性的值设为-1,表示rehash操作已完成。

集合的相关命令


Redis数据结构之集合对象相关推荐

  1. 「Redis数据结构」集合对象(Set)

    「Redis数据结构」集合对象(Set) 文章目录 「Redis数据结构」集合对象(Set) 一.概述 二.结构 三.编码转换 四.小结 一.概述 Set是Redis中的单列集合,其特点为不保证有序性 ...

  2. Redis数据结构之集合

    本文来说下Redis数据结构之集合 文章目录 概述 常用集合命令 相关命令 集合内的操作命令 集合间的操作命令 内部编码 intset(整数集合) hashtable(哈希表) 具体示例 应用场景 用 ...

  3. 「Redis数据结构」字符串对象(String)

    「Redis数据结构」字符串对象String 文章目录 「Redis数据结构」字符串对象String 一.概述 二.编码分类 int embstr row 三.小结 四.参考 一.概述 字符串数据类型 ...

  4. Redis:12---有序集合对象

    一.有序集合对象概述 它保留了集合不能有重复成员的特性, 但不同的是,有序集合中的元素可以排序.但是它和列表使用索引下标作为排序依据不同的是,它给每个元素设置一个分数(score)作为排序的依据 如下 ...

  5. Redis数据结构——整数集合-intset

    整数集合 整数集合是集合键的底层实现之一,当一个集合只包含整数值元素,并且这个集合的元素数量不多时,Redis就会使用整数集合作为集合键的底层实现. 1.整数集合实现: 整数集合是redis用于保存整 ...

  6. 理解 redis 中的 集合对象类型

    这篇我们来看看Redis五大类型中的第四大类型:集合类型,集合类型还是蛮有意思的,第一个是因为它算是只使用key的Dictionary简易版,这样说来的话,它就比Dictionary节省很多内存消耗, ...

  7. Redis数据结构-对象

    目录 前言 1.对象的类型与编码 1.1.类型 2.编码和底层实现 2.1.字符串对象 2.2.列表对象 2.3.哈希对象 2.4.集合对象 2.5.有序集合对象 参考 最后 前言 Redis并没有直 ...

  8. Redis数据结构之有序集合

    本文来说下Redis数据结构之集合 文章目录 概述 Redis有序集合的部分命令 相关命令 集合内 集合间 内部编码 ziplist(压缩列表) skiplist(跳跃表) 使用场景 本文参考 本文小 ...

  9. 第18章 Redis数据结构常用命令

    18-1 字符串的一些基本命令 18-1 :配置Spring关于Redis字符串的运行环境 <bean id="poolConfig" class="redis.c ...

  10. 深入剖析Redis系列(七) - Redis数据结构之列表

    前言 列表(list)类型是用来存储多个 有序 的 字符串.在 Redis 中,可以对列表的 两端 进行 插入(push)和 弹出(pop)操作,还可以获取 指定范围 的 元素列表.获取 指定索引下标 ...

最新文章

  1. 开启笔记本win7的虚拟热点,让你的本本变成wifi
  2. 【C语言】 strstr查找子字符串函数以及模拟实现讲解
  3. 这份GitHub万星的机器学习算法面试大全请大家注意查收
  4. 给定一个介于0和1之间的实数,类型为double,打印它的二进制表示
  5. mysql中的钱null,mysql 中null总结
  6. StackOverflow How to programmatically unplug replug an arbitrary USB device? 如何以编程方式拔出并重新插入任意USB设备
  7. Spring事务 Transaction rolled back because it has been marked as rollback-only
  8. day24-1 元类
  9. C++虚继承(二) --- C++ 对象的内存布局(上)(陈皓)
  10. 南邮CTF-MISC-Remove Boyfriend
  11. 【Python CheckiO 题解】Multicolored Lamp
  12. 审查元素找不到创建的元素_香奈儿除了珍珠,还有哪些你不知道的经典元素?答案在原文中找...
  13. Ubuntu移除mysql后重新安装
  14. 《Web漏洞防护》读书笔记——第7章,访问控制防护
  15. Atlantis poj1151 线段树扫描线
  16. HMTL基础学习之基础篇
  17. Android设置图标背景透明
  18. H.264开源解码器评测
  19. Cracking the Wall of Confinement: Understanding and Analyzing Malicious Domain Take-downs
  20. excel单元格内回车换行

热门文章

  1. 基于CList链表类的故障树分析算法的实现
  2. 【免费好用】节假日查询接口
  3. 谷歌翻译停服后,chrome无法自动翻译?解决办法来了~
  4. Linux 系统硬盘MBR转换为GPT格式并扩容
  5. python炫酷烟花表白源代码-python烟花效果的代码实例
  6. 浏览量(PV)、访客数(UV)、访问次数、跳出率
  7. 微分方程的Matlab解法
  8. 珠联网络棋牌游戏 v2.95a 官方
  9. 图形界面上的任意形状图形按钮
  10. 怎么同时给多个 Word 文档批量添加自定义的文字和图片水印