Hash、HASHTABLE底层原理【Redis对象篇】

🏆 作者简介:席万里
⚡ 个人网站:https://dahua.bloggo.chat/
✍️ 一名后端开发小趴菜,同时略懂Vue与React前端技术,也了解一点微信小程序开发。
🍻 对计算机充满兴趣,愿意并且希望学习更多的技术,接触更多的大神,提高自己的编程思维和解决问题的能力。

文章目录

  • 1.hash是什么?
  • 2.适用场景
  • 3.常用操作
    • 1.写操作
    • 2.读操作
  • 4.原理
  • 5.总结
  • HASTABLE
    • 1.HASHTABLE简述
    • 2.HASHTABLE结构
    • 3.渐进式扩容,缩容

1.hash是什么?

Redis Hash是一个field、value都为string的hash表,存储在Redis的内存中。

2.适用场景

适用于O(1)时间字典查找某个field对应数据的场景,比如任务信息的配置,就可以任务类型为field,任务配置参数为value。

3.常用操作

  • 创建:HSET、HSETNX
  • 查询:HGETALL、HGET、HLEN、HSCAN
  • 更新:HSET、HSETNX、HDEL
  • 删除:DEL

1.写操作

1、HSET,为集合对应field设置value数据。字段+值。
HSET key field value [field value …]
[图片]

[图片]

2、HSETNX,如果field不存在,则为集合对应设置value数据。如果存在则不设置。
[图片]

3、HDEL,删除指定字段field,可以一次删除多个。
4、DEL,删除Hash对象。
5、HMSET,可以设置多个键值对。在Redis4.0之前,HSET只能设置单个键值对,4.0之后,弃用HMSET,改用HSET。

2.读操作

1、HGETALL,查找全部数据。
[图片]

2、HGET,查询field对应的value。
3、HLEN,查找Hash中元素总数。
4、HSCAN,从指定位置查询一定数量的数据。

4.原理

Hash底层有两种编码结构,压缩列表和HASHTABLE。同时满足以下两个条件,用压缩列表:

  1. Hash对象保存的所有值和键的长度都小于64字节;
  2. Hash对象元素个数少于512个。
    两个条件任何一条不满足,编码结构就用HASHTABLE。
    ZIPLIST其实就是在数据量小的时候将数据紧凑排列,对应到Hash,就是将field-value当做entry放入ZIPLIST。查找key的时间复杂度O(N)。
    [图片]

HASHTABLE在之前无序集合SET中也有应用,区别就是,在SET中value始终为null,但是Hash中是有对应的值。查找key的时间复杂度O(1)。
[图片]

5.总结

1、Hash的编码方式是什么?
一个是ZIPLIST,一个是HASHTABLE。ZIPLIST适用于元素较少且单个元素长度较小的情况,其他情况使用HASHTABLE。

2、HASH为什么要用两种编码方式?
采用两种编码方式的原因是ZIPLIST更节约内存,所以在小数据量使用,而数据多时,需要使用HASHTABLE提高更高的查找、更新性能。

HASTABLE

别,这个模块还没结束呢。学了SET和HASH之后,我们都见到了底层有一个叫HASHTABLE的结构,接下来就去探究一下这是个啥。

1.HASHTABLE简述

简单点说,就是哈希表。那么有什么用呢?
就好比一本书,如果让你一页一页去找是不是很麻烦,要是有一个目录可以直接根据关键字就能定位,是不是效率就更高了。

2.HASHTABLE结构

// redis 5.0.5
typedef struct dictht {
    dictEntry **table;    /* 哈希桶数组,指向实际的hash存储 */
    unsigned long size;   /* 哈希表大小(桶数) */
    unsigned long sizemask; /* 哈希表大小掩码 */
    unsigned long used;   /* 哈希表已使用的桶数量 */
} dictht;

[图片]

3.渐进式扩容,缩容

// redis 5.0.5
typedef struct dict {
    dictht ht[2];         /* 目前使用的两个哈希表(用于rehash) */
    dictType *type;       /* 数据类型 */
    void *privdata;       /* 私有数据(通常为 NULL),保存需要传给那些类型特定函数的可选参数*/
    long rehashidx;       /* 正在进行的 rehash 操作的桶索引 */
    unsigned long iterators; /* 迭代器数量 */
} dict;

为了实现渐进式扩容,redis没有直接把dictht暴露给上层,而是再封装一层,如上。
可以看到dict结构里面,包含了两个dictht结构,也就是两个HASHTABLE结构。dictEntry是链表结构,也就是用拉链法解决哈希冲突,用的头插法。
[图片]

实际上平时用的都是一个HASHTABLE,在触发扩容之后,就会两个HASHTABLE同时使用,以下是详细流程:

  1. 首先,为新Hash表ht[1]分配空间。新表大小为第一个大于等于原表2倍used(已使用的桶数量)的2次方幂。然后迁移ht[0]数据到ht[1]。在ReHash(是指重新计算键的哈希值和索引值)进行期间,每次对字典执行增删改查操作,程序会顺带迁移当前rehashidx在ht[0]上对应的数据,并更新偏移索引。同时,部分情况周期函数也会进行迁移。(这里解释一下这个rehashidx是什么意思:字典同时是拥有ht[0]和ht[1],将rehashidx设置为0,表示rehash开始;在rehash期间,每次对字典crud,会顺带将ht[0]哈希表在rehashidx索引上的所有kv rehash到ht[1],当rehash完成后rehashidx+1;随着字典不断操作,最终ht[0]所有键值都会被rehash到ht[1],这时将rehashidx设置为-1,表示操作结束。注意:在渐进式rehash的过程,如果有crud,如果index大于rehashidx,访问ht[0],否则访问ht[1]。)
  2. 然后,随着字典不断执行,最终在某个时间点上,ht[0]的所有键值都会被Rehash至ht[1],此时再将ht[1]和ht[0]指针对象互换,同时把偏移索引rehashidx的值设为-1,表示Rehash已完成。
    既然知道了扩容的流程,那么扩容时机是什么时候呢?
    redis会根据负载因子的情况来扩容:
  3. 负载因子大于等于1,说明此时空间已经非常紧张。
  4. 负载因子大于5,此时即使有复制命令,也要进行Rehash扩容。
    负载因子:k=ht[0].used / ht[0].size
    如果扩容太大,但是数据已经减少了,就需要进行缩容,缩容也是渐进式的。那么什么时机缩容呢?
    当负载因子小于0.1,即负载率小于10%,此时进行缩容,新表大小为第一个等于原表used的2次方幂。

总之,ZIPLIST、HASHTABLE面试超级热点,不仅学习这些大致思路,还要掌握一些细节。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/934421.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv11改进,YOLOv11添加GSConv卷积+Slim-neck,助力小目标检测,二次创新C3k2结构

实时目标检测在工业和研究领域中具有重要意义。在边缘设备上,巨大的模型难以满足实时检测的要求,而由大量深度可分离卷积(depth-wise separable convolution)构建的轻量级模型又无法达到足够的精度。作者引入了一种新的轻量级卷积技术——GSConv,以减轻模型重量同时保持精…

利用Java爬虫MinC根据ID获取商品详情的完整指南

在当今数字化时代,获取商品详情数据对于市场分析、价格监控和竞争对手分析至关重要。Java作为一种强大且广泛使用的编程语言,非常适合开发复杂的爬虫系统。本文将详细介绍如何利用Java编写爬虫程序来根据商品ID获取商品详情,并提供完整的代码…

IP地址中的网络号:定义、作用与重要性

在计算机网络中,IP地址是每台设备的唯一标识。它由网络号和主机号两部分组成,其中网络号用于标识一个特定的网络,而主机号则用于区分该网络内的不同设备。网络号的正确分配和管理,是IP网络互联互通的基础。本文将带您走进网络号的…

java_连接数据库的方法_后端处理_前端调用_打通整体思路

参考:14 尚上优选项目-平台管理端-权限管理模块-开发角色管理接口(上)_哔哩哔哩_bilibili 第一步. 定义数据 在数据库中定义好数据(如role表格),在java后端定义好对应的实体类(Role类&#xf…

PHP富文本编辑器eWebEditor实战指南

本文还有配套的精品资源,点击获取 简介:eWebEditor是一个基于PHP的开源在线文本编辑器,提供类似Word的用户界面,简化了网页文本的创建和编辑过程。它广泛适用于博客、论坛、CMS等平台的内容管理,具备富文本编辑、表格…

docker nginx 部署vue 实例

1.安装docker https://blog.csdn.net/apgk1/article/details/144354588 2. 安装nginx docker 安装 nginx-CSDN博客 3. 复制 nginx-test 实例的一些文件到宿主机中,目前已 /home/jznh/路径演示 3.1 在/home/jznh/ 创建 conf html logs 三个文件夹,…

一个直接看央视频道的软件,可直接安装到TV

优点 打开无广告,直接自动默认打开央视频道加载速度快,切换频道响应快,不用转圈圈画质清晰,画质清晰无雪花频道多,差不多上百个频道 软件截图 下载链接 跳转原文下载

JavaEE之多线程的风险以及如何避免

上文我们了解了单线程以及线程的一些基本常见方法,但是多线程在一些方面会存在安全问题,此文我们来为多线程的安全 保驾护航!! 详情请见下文 1. 多线程带来的风险——线程安全 1.1 观察线程不安全 /*** 使用两个线程&#xff0c…

【OpenCV】直方图

理论 可以将直方图视为图形或曲线图,从而使您对图像的强度分布有一个整体的了解。它是在X轴上具有像素值(不总是从0到255的范围),在Y轴上具有图像中相应像素数的图。 这只是理解图像的另一种方式。通过查看图像的直方图,您可以直观地了解该…

MoeCTF2024-Web题解

目录 1、弗拉格之地的入口 2、垫刀之路01: MoeCTF?启动! 3、ez_http 4、ProveYourLove 5、弗拉格之地的挑战 6、ImageCloud前置 7、垫刀之路02: 普通的文件上传 8、垫刀之路03: 这是一个图床 9、垫刀之路05: 登陆网站 10、垫刀之路06: pop bas…

python学opencv|读取图像(六)读取图像像素RGB值

【1】引言 前序已经掌握了如何获取灰度图像的像素,文章链接为: python学opencv|读取图像(五)读取灰度图像像素-CSDN博客 实际上像素就像一个坐标轴,约束了图像的大小。 但实际上我们在学习过程中,对于同…

ThingsBoard规则链节点:RabbitMQ 节点详解

ThingsBoard 是一个开源的物联网平台,允许开发者快速构建IoT产品。它提供了设备连接、数据收集、处理和可视化等功能。为了实现高效的数据处理和消息传递,ThingsBoard 集成了多种消息队列服务,其中就包括了RabbitMQ。 RabbitMQ 是一个广泛使用…

如何创建基于udp的客户端和服务端

1.先创建好udpServer.hpp、udpServer.cc、udpClient.hpp、udpClient.cc的框架。 #pragma once #include <string> #include <iostream> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <cerrno> #include…

TCP 2

文章目录 Tcp状态三次握手四次挥手理解TIME WAIT状态 如上就是TCP连接管理部分 流量控制滑动窗口快重传 延迟应答原理 捎带应答总结TCP拥塞控制拥塞控制的策略 -- 每台识别主机拥塞的机器都要做 面向字节流和粘包问题tcp连接异常进程终止机器重启机器掉电/网线断开 Tcp状态 建…

ChatGPT Pro是什么

ChatGPT Pro 和 ChatGPT Plus 的区别主要体现在功能范围、适用场景和目标用户上。 ChatGPT Plus 功能 • 价格&#xff1a;20美元/月。 • 目标用户&#xff1a;针对个人用户设计。 • 主要特点&#xff1a; • 在高峰期响应速度更快。 • 使用高级模型&#xff08;如 GPT-4…

【开源免费】基于Vue和SpringBoot的桂林旅游景点导游平台(附论文)

博主说明&#xff1a;本文项目编号 T 079 &#xff0c;文末自助获取源码 \color{red}{T079&#xff0c;文末自助获取源码} T079&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…

C++ day3——C++核心

作业&#xff1a; 整理思维导图 2、整理课上代码 3、把课上类的三个练习题的构造函数写出来 1、定义一个矩形类Rec #include <iostream>using namespace std; class Rec {const int length;int width; public:Rec(int length,int width):length(length),width(width)…

目前Java后端就业前景到底怎么样?

很多人都说今年对于IT行业根本没有所谓的“金三银四”“金九银十”。在各大招聘网站或者软件上不管是大厂还是中小公司大多都是挂个招聘需求&#xff0c;实际并不招人&#xff1b;在行业内的程序员基本都已经感受到了任老前段时间口中所谓的“寒气”。 虽然事实确实是如此&…

倚光科技助力自由曲面设计与加工

近年来&#xff0c;自由曲面因其在光学、汽车、航空航天等领域的广泛应用&#xff0c;受到设计师和工程师的高度关注。自由曲面作为一种具有更高自由度的非球面透镜&#xff0c;能够在光学系统中实现更加精确的光线控制&#xff0c;优化像差校正&#xff0c;并且在满足功能需求…

算法论文/半监督1——2024最新半监督目标检测综述(CNN和Transformer)全文1.5W字

Semi-Supervised Object Detection: A Survey on Progress from CNN to Transformer 摘要 半监督学习的惊人进步促使研究人员探索其在计算机视觉领域内目标检测任务中的潜力。半监督对象检测 &#xff08;SSOD&#xff09; 利用小型标记数据集和较大的未标记数据集的组合。这…