三 字典

  字典是Hash对象的底层实现,比如用HSET创建一个HASH的对象,底层可能就是用一个字典实现的键值对。

字典的实现主要设计下面三个结构:

/*
* 哈希表节点
*/
typedef struct dictEntry { // 键
void *key; // 值
union {
void *val;
uint64_t u64;
int64_t s64;
} v; // 指向下个哈希表节点,形成链表
struct dictEntry *next; } dictEntry; /*
* 哈希表
*
* 每个字典都使用两个哈希表,从而实现渐进式 rehash 。
*/
typedef struct dictht { // 哈希表数组
// [JZ]: 即二维数组/链表
dictEntry **table; // 哈希表大小
unsigned long size; // 哈希表大小掩码,用于计算索引值
// 总是等于 size - 1
unsigned long sizemask; // 该哈希表已有节点的数量
unsigned long used; } dictht;

/*
 * 字典类型特定函数
 */
typedef struct dictType {     // 计算哈希值的函数
    unsigned int (*hashFunction)(const void *key);     // 复制键的函数
    void *(*keyDup)(void *privdata, const void *key);     // 复制值的函数
    void *(*valDup)(void *privdata, const void *obj);     // 对比键的函数
    int (*keyCompare)(void *privdata, const void *key1, const void *key2);     // 销毁键的函数
    void (*keyDestructor)(void *privdata, void *key);
    
    // 销毁值的函数
    void (*valDestructor)(void *privdata, void *obj); } dictType; /*
* 字典
*/
typedef struct dict { // 类型特定函数
dictType *type; // 私有数据
void *privdata; // 哈希表
dictht ht[]; // rehash 索引
// 当 rehash 不在进行时,值为 -1
int rehashidx; /* rehashing not in progress if rehashidx == -1 */ // 目前正在运行的安全迭代器的数量
int iterators; /* number of iterators currently running */ } dict;

他们之间的关系如下图:

- dict.type里会注册回调函数,用来实现计算哈希值(hashFunction(),redis使用MurmurHash2算法来计算哈希值(dictEncObjHash))等等功能,用dict.sizemask计算索引值,即dictentry[i]的下标值

- 键冲突:不同的键分配到同一个索引,就在这个dictentry[i]上构成单向链表

- rehash:哈希表有一个负载因子的概念,load_factor=ht[0].used/ht[0].size,当这个值大于等于1(或者满足以下条件),会进行rehash,也代表了保存的键值过多,进行重新的散列操作,从ht[0]转移所有的hashNode到ht[1]。

rehash过程中,dict.rehashidx用来标明是否在rehash(-1为非rehash),每做一个就加1,最终全部做完后,置为-1,然后将ht[1]的所有entry拷贝回ht[0],这样不需要一次性完成所有node的rehash,避免了rehash时的庞大而集中的计算量。

rehash过程中,如果有对字典的删除,查找和更新操作,可能会对ht[0]和ht[1]都进行操作,比如查找会先到ht[0]找,找不到会到ht[1]找,如果新建,则会保存到ht[1],ht[0]不做新增,保证ht[0]里的键值对只减不增,并随着rehash最终成为空表

[redis读书笔记] 第一部分 数据结构与对象 字典的更多相关文章

  1. [redis读书笔记] 第一部分 数据结构与对象 简单动态字符串

    本读书笔记主要来自于<<redis设计与实现>> -- 黄键宏(huangz) redis主要设计了字符串,链表,字典,跳跃表,整数集合,压缩列表来做为基本的数据结构,实现键值 ...

  2. [redis读书笔记] 第一部分 数据结构与对象 对象类型

    - 从前面redis的基本数据结构来看,可以看出,redis都是在基本结构(string)的基础上,封装了一层统计的结构(SDS),这样让对基本结构的访问能够更快更准确,提高可控制度. - redis ...

  3. [REDIS 读书笔记]第一部分 数据结构与对象 跳跃表

    下面是跳跃表的基本原理,REDIS的实现大致相同 跳跃表的一个特点是,插入NODE是通过随机的方式来决定level的,比较奇特 下面是skipList的一个介绍,转载来的,源地址:http://ken ...

  4. [redis读书笔记] 第一部分 数据结构与对象 对象特性

    一 类型检查和多态    类型检查,即有的命令是只针对特定类型的,如果类型不对,就会报错,此处的类型,是指的键类型,即robj.type.下面为有类型检查的命令: 对于某一种类型,redis下底层的实 ...

  5. [redis读书笔记] 第一部分 数据结构与对象 整数集合

    typedef struct intset { // 编码方式 uint32_t encoding; // 集合包含的元素数量 uint32_t length; // 保存元素的数组 int8_t c ...

  6. [redis读书笔记] 第一部分 数据结构与对象 压缩列表

    压缩列表是为了节省内存而设计的,是列表键和哈希键的底层实现之一. 压缩列表的逻辑如下,

  7. [redis读书笔记] 第一部分 数据结构与对象 链表

    二 链表 1.链表节点使用ListNode结构,是一个双向的链表,同时,还实现了一个控制所有ListNode的结构list: typedef struct listNode { // 前置节点 str ...

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

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

  9. 《javascript权威指南》读书笔记——第一篇

    <javascript权威指南>读书笔记——第一篇 金刚 javascript js javascript权威指南 由于最近想系统学习下javascript,所以开始在kindle上看这本 ...

随机推荐

  1. SpringBoot入门(一)

    1 简介 Spring Boot是快速搭建Spring工程的脚手架,简化配置与依赖关系(约定大于配置),让我们把精力集中在业务部分 2 简单入门事例 创建一个Hello World的Web工程 2.1 ...

  2. Java List集合的介绍与常用方法

    List接口的介绍 List接口简介: java.util.List接口继承自Collection接口,是单列集合的一个重要分支,习惯性地会将实现了List接口的对象称为List集合. 在List集合 ...

  3. python 条件判断的三元表达式

    示例:求两数中最大者 在JavaScript中代码如下: x = 1; y = 2; console.log(x > y ? x : y) 在python中代码如下: # 条件为真时的返回结果 ...

  4. hdu6621 二分加主席树

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6621 Problem Description You have an array: a1, a2,  ...

  5. webpack进阶用法你都get到了么?

    如何消除无用代码:打包自己的私有js库:实现代码分割和动态import提升初次加载速度:配置eslint规范团队代码规范:打包异常抓捕你都get到了么? 摇树优化:Tree Shaking webpa ...

  6. leetcode 最大水池

    leetcode 11题 水池最大容积 题目描述 给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) .在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 ( ...

  7. python3三元运算

    条件:简单的条件判断语句并且有返回值 作用:简化代码和装X 格式:为True执行的语句 if 判断条件 else 为False执行的语句 例子 def f(a, b): ""&qu ...

  8. python-review01

    # 1.使用while循环输出 1 2 3 4 5 6 8 9 10 count = 0 while count < 10: count += 1 if count == 7: continue ...

  9. Qt Installer Framework翻译(5-3)

    推广更新 创建在线安装程序,以便能够向安装产品的用户推广更新. 为了推广更新,需要执行以下步骤: 将待更新内容复制到package文件夹. 在package.xml文件中增加待更新组件的元素的值. 使 ...

  10. [洛谷P3621] [APIO2007] 风铃

    Description 你准备给弟弟 Ike 买一件礼物,但是,Ike 挑选礼物的方式很特别:他只喜欢那些能被他排成有序形状的东西. 你准备给 Ike 买一个风铃.风铃是一种多层的装饰品,一般挂在天花 ...