Redis_字典

时间:2023-02-12 07:30:11

阅读本文之前要了解的两件事情,第一,Redis是一种Key-Value数据库,第二,字典是一种保存键值对的抽象数据结构。所以不难猜出字典在Redis中应用一定很广泛,实际上,Redis数据库的底层实现就是字典,对数据库的增删查改也是构建在对字典的操作上。那么想要深入理解Redis,字典的解密是不可缺少的。接下来,就让我们一层一层解开指点的面纱,看看它的真面目。

首先看看Redis中有哪些地方使用到了字典

一, 数据库键空间

Redis是一个键值对数据库server,server中的每一个数据库都是一个RedisDB结构,当中RedisDb结构的dict字典保存了数据库中的全部键值对。我们将这个字典称为键空间(key space),键空间和用户直接所见的数据库是直接相应的

二。 Expires字典

Redis数据库结构是一个RedisDb结构,有一个属性expires也是字典,这个字典中保存了数据库中全部键的过期时间,我们称这个字典叫做过期字典

以下贴出RedisDb的数据结构。加深了理解。

三。 字典是Hash类型的底层实现之中的一个

这里之所以说是之中的一个。是应为Hash类型的实现能够是多种类型,在不同的场景下能够是不同的类型,但一个哈希键中包括的键值对照较多。有或者是键值对中元素都是比較长的字符串的时候。就会使用字典作为底层实现。否则就是压缩列表作为底层实现。

【注意】键空间中的键和过期字典中的键都指向都一个键对象,所以不会出现不论什么反复对象,也不会浪费内存空间。

然后我们来了解一下在Redis中字典是怎样实现的。

字典的定义在dict.h/dict中给出了,例如以下:

typedef struct dict {
dictType *type;
void *privdata;
dictht ht[2];
long rehashidx; /* rehashing not in progress if rehashidx == -1 */
int iterators; /* number of iterators currently running */
} dict;

这是一个哈希表。table数组中的每一个元素都是指向一个dictEntry结构的指针,size是哈希表的大小。也就是table数组的大小。sizemask属性总是等于size-1 ,sizemask和哈希值一起决定将一个键应该被放到那个数组上,used表示眼下哈希表有多少个节点,used/size 是一个哈希表的负载因子,这个因子决定了什么时候后对哈希表进行扩展和收缩。

typedef struct dictht {
dictEntry **table;
unsigned long size;
unsigned long sizemask;
unsigned long used;
} dictht;

以下是一个哈希表节点,每一个dictEntry结构都保持着一个键值对,当中next指针能够将多个哈希值同样的键值对连接在一起,一次来解决键冲突的问题(这里能够引申出哈希函数以及哈希冲突解决方式。Redis中使用的解决方式是链地址法,就是。假设多个值通过哈希函数得到的哈希值是同样的,那么就链接到这个地址后,另一种解决哈希冲突的方案。就是寻地址法。就是当出现哈希冲突的时候,对键值对在进行一个哈希函数。得到一个没有被占用的地址为止,这两种方案各有利弊,链地址法可能会退化成一个链表。寻地址法可能在后期插入时,全是冲突)

typedef struct dictEntry {
void *key;
union {
void *val;
uint64_t u64;
int64_t s64;
double d;
} v;
struct dictEntry *next;
} dictEntry;

另一个须要说的地方,就是哈希表的rehash

随着操作的不断运行,一个哈希表中保存的键值对会越来越多或者是越来越少,哈希表中键值对数量过多或者过少都是不好的,过多,就会相当于是多个链表。过少也不好,查找的命中率也会非常低。将哈希表的负载因子(used/size)维持在一个范围之类是最好的。所以,当哈希表的数量过大或者过小的时候。程序会对哈希表进行扩展或者收缩,

扩展好理解,假设size=4 ,可是used=8,相当于每一个键的后面都有个链,这样查找起来是费劲的。这个时候能够通过Rehash来进行完毕,注意dict数据结构中的那个

dictht ht[2],这里是两个dictht,当中ht[1]是空暇的,在进行扩展的时候现将ht[1]扩展成ht[0]的两倍,然后将ht[0]中的键值对一个一个哈希到ht[1]中去。最后将ht[1]设置为ht[0]

这里须要注意的是rehash的时机。通常是负载因子大于5的时候扩展,负载因子小于0.1的时候收缩,另一个问题是字典中有个属性是rehashidx。这个属性标志rehash的状态,假设是0,表示rehash正式開始。然后没rehash一个键值对。就将这个值加一,当ht[0]的值所有被转移到ht[1]的时候。就将这个值设置成-1。表示rehash操作完毕。

事实上还有非常多要说的。比方渐进式rehash,渐进式就说说rehash过程不是一次性完毕的,而是分多次,渐进式完毕的,在rehash过程中,全部的删除,查找。更新都会在两个哈希表中进行。比如,假设查找一个元素,ht[0]中没有,那么就去ht[1]中查找,新加入的一律都是加入到ht[1]中,ht[0]中不再进行不论什么加入操作

Redis_字典的更多相关文章

  1. redis_字典_哈希hash

    字典.哈希表基本数据结构 redis字典使用哈希表作为底层实现,基本结构就是数组+散列 typedef struct dictht { // 哈希表数组 dictEntry **table; // 哈 ...

  2. redis中关于过期键的删除策略

    我们已经了解到了Redis是一种内存数据库,Redis中数据都是以key-value的形式存储在内存中.由Redisserver来维护和管理这部分内存,内存是何足珍贵,不须要的数据或者是已经使用过的无 ...

  3. 【DG】Oracle_Data_Guard官方直译

    [DG]Oracle Data Guard官方直译 1 Oracle Data Guard 介绍   Oracle Data Guard概念和管理10g版本2   Oracle Data Guard ...

  4. DVWA实验之Brute Force(暴力破解)- Low

    DVWA实验之Brute Force-暴力破解- Low     这里开始DVWA的相关实验~   有关DVWA环境搭建的教程请参考: https://www.cnblogs.com/0yst3r-2 ...

  5. Oracle错误览表

    Oracle 错误总结及问题解决 ORA     本文转自:https://www.cnblogs.com/zhangwei595806165/p/4972016.html  作者@承影剑 ORA-0 ...

  6. Javacript实现字典结构

    字典是一种用[键,值]形式存储元素的数据结构.也称作映射,ECMAScript6中,原生用Map实现了字典结构. 下面代码是尝试用JS的Object对象来模拟实现一个字典结构. <script& ...

  7. python 数据类型 ----字典

    字典由一对key:value 组成的 python中常用且重量级的数据类型 1. key , keys, values 字典由一对key:value 组成的 python中常用且重量级的数据类型 1. ...

  8. 增强版字典DictionaryEx

    代码 public class DictionaryEx<TKey, TValue> : IDictionary<TKey, TValue> { /// <summary ...

  9. python学习笔记(字符串操作、字典操作、三级菜单实例)

    字符串操作 name = "alex" print(name.capitalize()) #首字母大写 name = "my name is alex" pri ...

随机推荐

  1. Hadoop中的问题排查思路

    一.概述: 在实际使用hadoop的过程中,由于涉及到多台服务器.每台机器上可能还有多个服务等.所以当集群环境出现问题时,快速定位到错误出现的地方尤为重要. 在排查错误的过程中,基本上就是通过既有的工 ...

  2. MySQL删除重复记录的方法

    参考网上的方法,总结了产出重复记录的方法,欢迎交流. 参考:http://www.cnblogs.com/nzbbody/p/4470638.html 方法1:创建一个新表临时储存数据 假设我们有一个 ...

  3. 微信小程序demo豆瓣图书

    最近微信小程序被炒得很火热,本人也抱着试一试的态度下载了微信web开发者工具,开发工具比较简洁,功能相对比较少,个性化设置也没有.了解完开发工具之后,顺便看了一下小程序的官方开发文档,大概了解了小程序 ...

  4. Mac上使用虚拟机搭建Hadoop集群

    一. mini安装一台centos到虚拟机上 安装过程参考这篇博客http://www.linuxdown.net/install/setup/2015/0906/4053.html 二. 修改网络配 ...

  5. 【多媒体封装格式详解】--- AAC ADTS格式分析

    ADTS全称是(Audio Data Transport Stream),是AAC的一种十分常见的传输格式. 记得第一次做demux的时候,把AAC音频的ES流从FLV封装格式中抽出来送给硬件解码器时 ...

  6. Linux内核分析作业第五周

    系统调用的三个层次(下) 一.给MenuOS增加time和time-asm命令 1.克隆并自动编译 MenuOS rm menu -rf 强制删除原menu文件 git clone https://g ...

  7. 修改redis 持久化路径和日志 路径 ,修改kafka日志路径

    redis修改持久化路径和日志路径 vim redis.conf logfile /data/redis_cache/logs/redis.log #日志路径 dir /data/redis_cach ...

  8. Linux重定向与管道

    程序执行时默认会打开3个流,标准输入.标准输出.标准错误. Redirection The shell interprets the symbols <,>, and >> a ...

  9. linux UIO

    UIO(linux Userspace I/O子系统)用户空间设备驱动I/O技术介绍(由www.169it.com搜集整理) UIO(Userspace I/O)是运行在用户空间的I/O技术.Linu ...

  10. Spark Streaming源码分析 &ndash&semi; JobScheduler

    先给出一个job从被generate到被执行的整个过程在JobGenerator中,需要定时的发起GenerateJobs事件,而每个job其实就是针对DStream中的一个RDD,发起一个Spark ...