概念

  字典,又称为符号表、关联数组或映射(map),是一种用于保存键值对(key-value pair)的抽象数据结构。字典中每个键都是独一无二的,程序可以根据键来更新值,或者删除整个键值对。

用途

  1. Redis的数据库就是使用字典来作为底层实现
  2. 字典还是哈希键的底层实现之一。当一个哈希键包含的键值对比较多,又或者键值对中的元素都是比较长的字符串时,Redis就会使用字典作为哈希键的底层实现。

字典的实现

  Redis的字典使用哈希表作为底层实现,一个哈希表里面可以有多个哈希表节点,而每个哈希表节点就保存了字典中的一个键值对。

 (Redis中dict是hash键的底层实现之一,而dict的底层又采用了hash表。hash表dictht包含了一个dictEntry数组,size记录了hash表的大小,sizemask始终等于size-1,还有一个used记录了已有节点的数量

  hash表节点dictEntry是一个键值对对象,另外还有一个next指针,指向下一个dictEntry,通过指针连接在一起,可以解决键冲突的问题

  )

哈希表

  1. table : 一个数组,数组中每个元素都是一个指向dict.h/dictEntry(哈希表节点)结构的指针,而每个dictEntry都保存了一个键值对
  2. size:记录了hash表的大小,也就是table数组的大小
  3. used:记录了hash表已有哈希表节点(键值对)的数量
  4. sizemask:总是等于size-1 

哈希表节点

  1. key:保存键
  2. v :保存键值对中的值,可以是一个指针,或者一个uint64_t整数,又或者是一个int64_t整数
  3. next :只想两一个哈希表节点的指针,多个指针将多个哈希值相同的键值对连接在一起,解决了键冲突的问题

字典

  1. type : 是一个指向dictType的指针,每一个dictType结构保存了一簇用于操作特定类型键值对的函数,Redis会为用途不同的字典设置不同的类型特定函数
  2. privdata : 保存了需要传给那些特定函数的可选参数
  3. ht[2] : 包含两个项(hash表)的数组,一般只用ht[0],ht[1]只有在rehash时使用
  4. trehashidx:记录rehash目前的进步,如果没在进行rehash,那么值为-1

解决键冲突

  Redis根据键值对的键计算出哈希值喝索引值,然后根据索引值,将包含新键值对的哈希表节点放到哈希表数组的指定索引上面。

  当两个或者以上数量的键被分配到哈希表数组的同一索引上面时,我们称这些键发生了冲突。

   Redis的哈希表采用链地址法解决键冲突。每个哈希表节点都有一个next指针,多个哈希表节点用next指针连接在一起,多个节点用这个单向链表连接起来,这就解决了链冲突。

Rehash

  1. 扩展操作:ht[1]的大小为第一个大于等于ht[0].used*2的2n(2的n次方)
  2. 收缩操作:ht[1]的大小为第一个大于等于ht[0].used的2n

当满足以下任意一个条件时,程序会自动进行扩展操作:

  • 服务器没有正在执行BGSAVE命令或者BGREWRITEAOF命令,并且哈希表负载因子大于等于1
  • 服务器正在执行BGSAVE或者BGREWRITEAOF命令,并且哈希表负载因子大于等于5
  • 负载因子计算公式:load_factor = ht[0].used / ht[0].size

rehash步骤:

  • 为字典ht[1]分配空间
  • 将保存在ht[0]中的所有键值对rehash到ht[1]上
  • ht[0]所有键值对迁移完后,释放ht[0],将ht[1]设置为htp[0],并在ht[1]创建一个空白哈希表,为下一次rehash做准备

渐进式rehash

  为避免rehash对服务器性能的影响,服务器不是一次性将ht[0]力所有的键值对全部rehash到ht[1]中,而是分多次,渐进式的rehash到ht[1]中

详细步骤:

  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完成

在rehash过程中,字典同时拥有ht[0]和ht[1]两个哈希表,期间字典的删除,查找,更新等操作会在两个哈希表进行。例如查找,先在ht[0]查找,如果没有就在ht[1]查找。另外在rehash期间,新添加的字典的键值对一律会保存到ht[1]中,ht[0]则不再进行任何添加操作,这保证ht[0]包含的数量只减不增,最终变为空表。

Redis之字典的更多相关文章

  1. 深入redis内部--字典实现

    redis的字典定义和实现在dict.h和dict.c文件中. 1.字典结构 typedef struct dict { dictType *type; //定义了字典需要的函数 void *priv ...

  2. Redis的字典扩容与ConcurrentHashMap的扩容策略比较

    本文介绍Redis的字典(是种Map)扩容与ConcurrentHashMap的扩容策略,并比较它们的优缺点. (不讨论它们的实现细节) 首先Redis的字典采用的是一种‘’单线程渐进式rehash‘ ...

  3. 【Redis】字典

    Redis 字典 基本语法 字典是Redis中的一种数据结构,底层使用哈希表实现,一个哈希表中可以存储多个键值对,它的语法如下,其中KEY为键,field和value为值(也是一个键值对): HSET ...

  4. Redis的字典(dict)rehash过程源代码解析

    Redis的内存存储结构是个大的字典存储,也就是我们通常说的哈希表.Redis小到能够存储几万记录的CACHE,大到能够存储几千万甚至上亿的记录(看内存而定),这充分说明Redis作为缓冲的强大.Re ...

  5. python redis存入字典序列化存储

    在python中通过redis hset存储字典时,必须主动把字典通过json.dumps()序列化为字符串后再存储, 不然hget获取后将无法通过json.loads()反序列化为字典 序列化存储 ...

  6. redis列表,字典,管道,vue安装,创建项目

    redis mysql,redis,mogondb 1.mysql,oracle:关系型数据库,有表概念 2.redis,mongodb/nosql:非关系型数据库 没有表概念 mongodb存储在硬 ...

  7. redis学习-字典

    1.字典作用 实现数据库键空间(key space): 用作 Hash 类型键的底层实现之一: 2.字典实现的数据结构 typedef struct dict { // 特定于类型的处理函数 dict ...

  8. 深入理解Redis 数据结构—字典

    字典,又称为符号表.关联数组或映射,是一种用于保存键值对的抽象数据结构.在字典中,一个键可以和一个值进行关联,这些关联的键和值称为键值对.键值对中键是唯一的,我们可以根据键key通过映射查找或者更新对 ...

  9. spring-boot集成6:集成redis实现字典缓存功能

    Why redis? redis是基于内存的key-value系统,可以用作缓存中间件或者消息中间件,spring-boot提供了方便的方式和redis集成. 1.maven依赖 <!--red ...

随机推荐

  1. 【asp.net core 系列】10 实战之ActionFilter

    0.前言 在上一篇中,我们提到了如何创建一个UnitOfWork并通过ActionFilter设置启用.这一篇我们将简单介绍一下ActionFilter以及如何利用ActionFilter,顺便补齐一 ...

  2. docker安装mysql,设置mysql初始密码

    docker安装mysql,只需要2分钟就可以完成 docker search mysql 拉取mysql镜像(https://hub.docker.com/_/mysql) docker pull ...

  3. 【Python】使用Selenium实现淘宝抢单

    最近,小明为了达成小姐姐的愿望,在某宝买到心仪的宝贝,再加上又迷上了python,就通过python轻而易举地实现了(个人声明:对Java来说,这并不是背叛). 需求分析&前期准备 需求其实很 ...

  4. Idea+springboot入坑之路

    环境准备 IDEA 社区版: 2019.3 jdk: 1.8.0_241 tomcat: 7.0.99 maven: 3.6.3 spring-boot:2.2.5.RELEASE 插件 spring ...

  5. Linux hostname主机名配置文件/etc/hosts详解

    这篇文章为大家介绍linux hostname主机名配置文件/etc/hosts,包括主机名的用途.配置文件的操作方法等,有需要的朋友,可以参考下 1.什么是Linux主机名 无论在局域网还是INTE ...

  6. 用JQuery解析获取JSON数据

    JSON 是一种比较方便的数据形式,下面使用$.getJSON方法,实现获得JSON数据和解析,都挺方便简单的.从http://api.flickr.com/services/feeds/photos ...

  7. 问题 C: 最短路径

    问题 C: 最短路径 在洛谷上刷最短路的题然后被老师拉回去做算法笔记上面的题... 拿到这道题,先确定所有路径唯一,然后是无向边,那么对于边权处理,直接赋值为2的k次方就可以了,然后直接跑最短路. 这 ...

  8. Spring Security(三) —— 核心配置解读

    摘要: 原创出处 https://www.cnkirito.moe/spring-security-3/ 「老徐」欢迎转载,保留摘要,谢谢! 3 核心配置解读 上一篇文章<Spring Secu ...

  9. 初探numpy——numpy常用通用函数

    numpy通用函数 快速的逐元素数组函数,也可以称为ufunc,对ndarray数据中的元素进行逐元素操作的函数 一元通用函数 函数名 描述 abs.fabs 取绝对值 sqrt 计算平方根,等同于a ...

  10. 使用 PostCSS 进行 CSS 处理

    在 Web 应用开发中,CSS 代码的编写是重要的一部分.CSS 规范从最初的 CSS1 到现在的 CSS3,再到 CSS 规范的下一步版本,规范本身一直在不断的发展演化之中.这给开发人员带来了效率上 ...