博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
redis 系列5 数据结构之字典(上)
阅读量:6418 次
发布时间:2019-06-23

本文共 3303 字,大约阅读时间需要 11 分钟。

原文:

一. 概述

  字典又称符号表(symbol table),关联数组(associative array), 映射(map),是一种用于保存键值对(key-value pair)的抽象数据结构。在字典中,一个key和一个value进行关联称为键值对。在字典中每个键都是唯一的,程序可以在字典中根据键查找关联的值,或通过键更新删除值等操作。在C语言中并没有内置这种数据结构,因此Redis构建了自己的字典实现。在Redis中应用广泛, 对数据库的增,删,查,改 都是构建在对字典的操作之上的。

-- 例1127.0.0.1:6379> set msg "hello world"OK127.0.0.1:6379> get msg"hello world"

  在例1中数据库创建一个键为"msg",值为"hello world"的键值对,这个键值对就是保存在数据库的字典里面。字典还是哈希键的底层实现之一,当哈希键包含的键值对比较多,或者键值对中的元素都是比较长的字符串时,Redis就会使用字典作为哈希键的底层实现。

-- 例2: website是一个包含3个键值对的哈希键(也叫哈希表),哈希键(key)为 website,哈希键的节点键是:数据库名字,哈希键的节点值是:网址    127.0.0.1:6379> hmset website redis "Redis.io" mariadb "mariadb.org" mongodb "mongodb.org" OK127.0.0.1:6379> hlen website(integer) 3127.0.0.1:6379> hgetall website1) "redis"2) "Redis.io"3) "mariadb"4) "mariadb.org"5) "mongodb"6) "mongodb.org"

  在例2中,website哈希键的底层实现就是一个字典。字典中包含了3个键值对。字典除了用来实现数据库和哈希键之处,Redis在后续学习中会看到各种不同应用。

 

二. 字典的实现

   一个哈希(键)表里面可以有多个哈希节点(key-vlaue), 每个哈希节点保存了字典的一个键值对。下面三个小节将分别介绍Redis的哈希表,哈希表节点,以及字典的实现。

  2.1 哈希表定义

typedef struct dictht      {         //哈希表数组,C语言中,*号是为了表明该变量为指针,有几个* 号就相当于是几级指针,这里是二级指针,理解为指向指针的指针         dictEntry **table;         //哈希表大小         unsigned long size;         //哈希表大小掩码,用于计算索引值         unsigned long sizemask;         //该哈希已有节点的数量          unsigned long used;      }dictht;

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

    例如:上面例2中,哈希表叫website,  对应一个dictht 结构,键值对table数组值是[3], 哈希表size值是3,索引值sizemask值是2,已有节点数量used值是3。

  2.2 哈希表节点定义 (键值对)

//哈希表节点定义dictEntry结构表示,每个dictEntry结构都保存着一个键值对。    typedef struct dictEntry      {         //键         void *key;         //值         union{           void *val;            uint64_tu64;            int64_ts64;            }v;         // 指向下个哈希表节点,形成链表         struct dictEntry *next;      }dictEntry;

    上面dictEntry 结构中,key属性保存着键值中的键,而v属性则保存着键值对中的值,其中键值(v属性)可以是一个指针,或uint64_t整数,或int64_t整数。 next属性是指向另一个哈希表节点的指针,这个指针可以将多个哈希值相同的键值对连接在一起,解决键冲突问题。

    下图通过next指针,将两个索引值相同(索引是2)的键k1和k0连接在一起。

  2.3 字典定义

// Redis中的字典由dict.h/dict结构表示          typedef struct dict      {         //类型特定函数         void *type;         //私有数据         void *privdata;         //哈希表         dictht ht[2];         // rehash 索引         int  trehashidx;       }dict;

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

typedef struct dictType      {         //计算哈希值的函数         unsigned int  (*hashFunction) (const void *key);         //复制键的函数         void *(*keyDup) (void *privdata,const void *key);         //复制值的函数         void *(*keyDup) (void *privdata,const void *obj);          //复制值的函数         void *(*keyCompare) (void *privdata,const void *key1, const void *key2);         //销毁键的函数         void (*keyDestructor) (void *privdata, void *key);         //销毁值的函数         void (*keyDestructor) (void *privdata, void *obj);      }dictType;
View Code

    ht属性是一个包含两个项的数组,数组中的每个项都是一个dictht哈希表, 一般情况下,字典只使用ht[0] 哈希表, ht[1]哈希表只会对ht[0] 哈希表进行rehash时使用。另一个和rehash有关的属性是rehashidx,它记录了rehash目前的进度,如果目前没有进行rehash,值为-1。下面图是一个没有进行rehash的字典。

  rehash是指渐进式的哈希,一张表是旧表,一张表是新表,当hashtable的大小需要动态改变的时候,旧表中的元素就往新开辟的新表中迁移,当下一次变动大小,当前的新表又变成了旧表,以此达到资源的复用和效率的提升。

转载地址:http://czvra.baihongyu.com/

你可能感兴趣的文章
mysql中show processlist过滤和杀死线程
查看>>
最新Sublime Text 2 激活 汉化
查看>>
基础数据类型之字典
查看>>
第七次作业
查看>>
Oracle中NVARCHAR2与VARCHAR2的区别
查看>>
php debug
查看>>
Ubuntu构建LVS+Keepalived高可用负载均衡集群【生产环境部署】
查看>>
lvm实现快速备份文件及数据库,lvm快照原理
查看>>
设计模式之Factory Method(工厂方法)
查看>>
10K入职linux运维岗位小伙伴感谢信及面试经历分享
查看>>
zookeeper入门之Curator的使用之几种监听器的使用
查看>>
[转]Reporting Service部署之访问权限
查看>>
innerxml and outerxml
查看>>
validform校验框架不显示错误提示
查看>>
flink 获取上传的Jar源码
查看>>
Spring Data JPA Batch Insertion
查看>>
UEditor自动调节宽度
查看>>
JAVA做验证码图片(转自CSDN)
查看>>
Delphi TServerSocket,TClientSocket实现传送文件代码
查看>>
JS无聊之作
查看>>