Redis数据结构之集合对象
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数据结构之集合对象相关推荐
- 「Redis数据结构」集合对象(Set)
「Redis数据结构」集合对象(Set) 文章目录 「Redis数据结构」集合对象(Set) 一.概述 二.结构 三.编码转换 四.小结 一.概述 Set是Redis中的单列集合,其特点为不保证有序性 ...
- Redis数据结构之集合
本文来说下Redis数据结构之集合 文章目录 概述 常用集合命令 相关命令 集合内的操作命令 集合间的操作命令 内部编码 intset(整数集合) hashtable(哈希表) 具体示例 应用场景 用 ...
- 「Redis数据结构」字符串对象(String)
「Redis数据结构」字符串对象String 文章目录 「Redis数据结构」字符串对象String 一.概述 二.编码分类 int embstr row 三.小结 四.参考 一.概述 字符串数据类型 ...
- Redis:12---有序集合对象
一.有序集合对象概述 它保留了集合不能有重复成员的特性, 但不同的是,有序集合中的元素可以排序.但是它和列表使用索引下标作为排序依据不同的是,它给每个元素设置一个分数(score)作为排序的依据 如下 ...
- Redis数据结构——整数集合-intset
整数集合 整数集合是集合键的底层实现之一,当一个集合只包含整数值元素,并且这个集合的元素数量不多时,Redis就会使用整数集合作为集合键的底层实现. 1.整数集合实现: 整数集合是redis用于保存整 ...
- 理解 redis 中的 集合对象类型
这篇我们来看看Redis五大类型中的第四大类型:集合类型,集合类型还是蛮有意思的,第一个是因为它算是只使用key的Dictionary简易版,这样说来的话,它就比Dictionary节省很多内存消耗, ...
- Redis数据结构-对象
目录 前言 1.对象的类型与编码 1.1.类型 2.编码和底层实现 2.1.字符串对象 2.2.列表对象 2.3.哈希对象 2.4.集合对象 2.5.有序集合对象 参考 最后 前言 Redis并没有直 ...
- Redis数据结构之有序集合
本文来说下Redis数据结构之集合 文章目录 概述 Redis有序集合的部分命令 相关命令 集合内 集合间 内部编码 ziplist(压缩列表) skiplist(跳跃表) 使用场景 本文参考 本文小 ...
- 第18章 Redis数据结构常用命令
18-1 字符串的一些基本命令 18-1 :配置Spring关于Redis字符串的运行环境 <bean id="poolConfig" class="redis.c ...
- 深入剖析Redis系列(七) - Redis数据结构之列表
前言 列表(list)类型是用来存储多个 有序 的 字符串.在 Redis 中,可以对列表的 两端 进行 插入(push)和 弹出(pop)操作,还可以获取 指定范围 的 元素列表.获取 指定索引下标 ...
最新文章
- 开启笔记本win7的虚拟热点,让你的本本变成wifi
- 【C语言】 strstr查找子字符串函数以及模拟实现讲解
- 这份GitHub万星的机器学习算法面试大全请大家注意查收
- 给定一个介于0和1之间的实数,类型为double,打印它的二进制表示
- mysql中的钱null,mysql 中null总结
- StackOverflow How to programmatically unplug replug an arbitrary USB device? 如何以编程方式拔出并重新插入任意USB设备
- Spring事务 Transaction rolled back because it has been marked as rollback-only
- day24-1 元类
- C++虚继承(二) --- C++ 对象的内存布局(上)(陈皓)
- 南邮CTF-MISC-Remove Boyfriend
- 【Python CheckiO 题解】Multicolored Lamp
- 审查元素找不到创建的元素_香奈儿除了珍珠,还有哪些你不知道的经典元素?答案在原文中找...
- Ubuntu移除mysql后重新安装
- 《Web漏洞防护》读书笔记——第7章,访问控制防护
- Atlantis poj1151 线段树扫描线
- HMTL基础学习之基础篇
- Android设置图标背景透明
- H.264开源解码器评测
- Cracking the Wall of Confinement: Understanding and Analyzing Malicious Domain Take-downs
- excel单元格内回车换行