三 字典

  字典是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. js最简单的编写地点

    1. 在哪里? 在浏览器的控制台. 2. 有什么作用? 方便快捷的测试纯js代码语句. 3. 如何使用? Google浏览器为例:  按 F12键  打开 开发者工具  (或者 浏览器工具栏 => ...

  2. js中如何将伪数组转换成数组

    伪数组:不能调用数组的方法, 1.对象是按索引方式存储数据的 2.它具备length属性 {0:'a',1:'b',length:2} //es5伪数组转换成数组 let args = [].slic ...

  3. php获取本年、本月、本周时间戳和日期格式

    时间戳格式: //获取今日开始时间戳和结束时间戳 $beginToday=mktime(0,0,0,date('m'),date('d'),date('Y')); $endToday=mktime(0 ...

  4. 《Java核心技术》 JVM指令集

    https://www.jianshu.com/p/bc91c6b46d7b

  5. linux下 Error in 'python3':free(): invalid pointer

    linux下坑人的报错!折腾了好久. 现象:这次是一个底层库 C++,底层库之上一层SDK C++,之上再一层so库,用python调用SDK.然后python层依赖了opencv和SDK,调换ope ...

  6. arima.predict()参数选择以及相关的一些问题

    在使用a ri ma进行模型建立时,需要注意以下几点 1.参数选择上predict必须起始时间在原始的数据及当中的,在下例中就是说2017必须在数据集里面,而2019不受限制,只哟在2017后面就好了 ...

  7. numpy 数组的计算

    一.数组和数的计算 数组和数计算,数组中的每个元素和数进行计算 1.加 import numpy as np arr1 = np.arange(12).reshape(3, 4) print(arr1 ...

  8. JVM内存布局及GC知识

    一.JVM运行时内存布局 按java 8虚拟机规范的原始表达:(jvm)Run-Time Data Areas, 暂时翻译为"jvm运行时内存布局". 从概念上大致分为6个(逻辑) ...

  9. 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果

    本文首发于先知社区: https://xz.aliyun.com/t/7096 前言 作为一名安全研究人员(java安全菜鸡),知道拿到exp怎么打还不够,还得进一步分析exp构造原理与漏洞原理才行. ...

  10. 【Oracle】复制表结构和表数据

    1.既复制表结构也复制表数据:CREATE TABLE tab_new AS SELECT * FROM tab_old; 2.只复制表结构:CREATE TABLE tab_new AS SELEC ...