当前位置: 首页 > news >正文

【Redis_Day6】Hash类型

【Redis_Day6】Hash类型

  • Hash类型
  • 操作hash的命令
    • hset:设置hash中指定的字段(field)的值(value)
    • hsetnx:想hash中添加字段并设置值
    • hget:获取hash中指定字段的值
    • hexists:判断hash中是否有指定的字段
    • hdel:删除hash中指定的字段
    • hkeys:获取hash中所有的字段
    • hvals:获取hash中所有的值
    • hgetall:获取hash中所有字段和其对应的值
    • hmget:一次获取hash中多个字段的值
    • hlen:获取hash中所有字段的个数
    • hincrby:给hash中指定字段对应的值 加n(n是整数)
    • hincrbyfloat:给hash中指定字段对应的值 加n(n是浮点数)
    • hash相关命令小结
  • hash内部编码
  • hash的应用
    • 作为缓存
      • 三种缓存方式对比
  • 高内聚低耦合

Hash类型

⼏乎所有的主流编程语⾔都提供了哈希(hash)类型,它们的叫法可能是哈希、字典、关联数组、映射。

在Redis中,哈希类型是指值本⾝⼜是⼀个键值对结构,形如key="key",value={{field1,value1},…,{fieldN,valueN}}。
哈希类型中的映射关系通常称为field-value,⽤于区分Redis整体的键值对(key-value),使用过程中要注意value在不同上下⽂的作⽤。

如下是字符串和哈希类型的对比:
在这里插入图片描述
redis自身就是键值对结构。
redis自身的键值对就是通过hash的方式来组织的。
针对一个键值对来说,其中的value同样可以是键值对,该键值对的类型是hash。

操作hash的命令

使用下列h系列命令的前提:key对应的value必须是hash类型。

hset:设置hash中指定的字段(field)的值(value)

总结hset的用法:
hset key field value [field value ...]:设置key的值,值的类型是hash。对一个key,可以一次给它设置多个field-value。返回值是添加的字段field的个数。如果key不存在,先创建key。
field-value中的value要求是字符串类型。
在这里插入图片描述在hset命令中,设置字段field1的值时,如果field1存在,那么本次设置的value会覆盖field1原来的值。

hsetnx:想hash中添加字段并设置值

hsetnx命令也是给字段设置值,但是要求字段不存在才能设置成功,也就是在hash中新建字段field1并给它设置值。

总结hsetnx的用法:
hsetnx key field1 value:key中不存在field1,添加field1并设置它的值为value,并返回1。如果field已存在,则操作无效,返回0。
命令成功前提是key存在且key中不存在field1。

在这里插入图片描述

hget:获取hash中指定字段的值

总结hget的用法:
hget key1 field1:获取key1中field1对应的value。返回值是fileld1对应的值或nil。
在这里插入图片描述

hexists:判断hash中是否有指定的字段

总结hexists的用法:
exists key field:去key对应的hash类型的value中找,有没有字段field。找到了返回1,没找到返回0。
在这里插入图片描述

hdel:删除hash中指定的字段

总结hdel的用法:
hdel key field [field ...]:删除key中指定的field,可以一次性删除多个。返回值是本次操作成功删除的字段个数。
在这里插入图片描述

hdel命令是删除key中指定的字段,通用命令del是删除key。

hkeys:获取hash中所有的字段

总结hkeys的用法:
hkeys key:根据key找到对应的hash,然后遍历该hash,获取hash中的所有字段,返回值是字段列表。
在这里插入图片描述

hvals:获取hash中所有的值

总结hvals的用法:
hvals key:根据key找到对应的hash,然后遍历hash,获取hash中所有的值。返回值是值列表。
在这里插入图片描述
hkeys和hvals命令操作起来都是存在一定风险的。这两个命令的时间复杂度都是O(N),N是哈希的元素个数,如果哈希非常大,执行这两个命令的时间会很长,会导致redis服务器堵塞,无法给其他客户端提供服务。

hgetall:获取hash中所有字段和其对应的值

总结hgetall的用法:
hgetall key:遍历key对应的value中所有的field-value,并输出。
在这里插入图片描述hgetall命令也是危险的操作。
在使⽤hgetall时,如果哈希元素个数⽐较多,会存在阻塞Redis的可能。如果开发⼈员只需要获取部分field,可以使⽤hmget,如果⼀定要获取全部field,可以尝试使⽤hscan命令
hscan是渐进式遍历,即hscan命令遍历hash的时候,每次只遍历hash中的一部分,连续执行多次hscan命令,才能完整整个遍历。hkeys,hvals,hgetall三个命令遍历hash的时候都是一次性遍历完全部hash。

hmget:一次获取hash中多个字段的值

总结hmget的用法:
hmget key field [field ...]: 一次获取hash中多个指定字段的值。返回值是对应字段的值或nil。
在这里插入图片描述

hlen:获取hash中所有字段的个数

总结hlen的用法:
hlen key:获取hash中所有字段的个数,返回值是字段的个数。
在这里插入图片描述执行hlen命令是不用遍历的。

hincrby:给hash中指定字段对应的值 加n(n是整数)

field-value中的value也可以当做数字来处理。

总结hincrby的用法:
hincrby key field incrment:给field对应的value 加上incrment。返回值是field的新值。
在这里插入图片描述

hincrbyfloat:给hash中指定字段对应的值 加n(n是浮点数)

hincrbyfloat是hincrby的浮点数版本。

hash相关命令小结

在这里插入图片描述
在这里插入图片描述
其中,hstrlen key field计算的是field-value中的value的长度。

hash内部编码

hash的内部编码有两种,分别是ziplist(压缩列表)hashtable(哈希表)

压缩的本质是针对数据进行重新编码。
不同的数据,有不同的特点,结合这些特点进行精妙的设计(压缩算法),重新编码之后,就能缩小体积。比如一个字符串abc0000000000000efg,重新编码后字符串变成了abc13[13]efg。

zipllist内部的数据结构也是精心设计的,相比于hashtable存储hash会存在浪费空间的问题,redis内部用ziplist类型存储hash,能节省内存空间。

ziplist的缺点,读写元素时候速度较慢,如果hash中元素个数少,慢的不明显,但是如果元素个数太多,就很慢了。

所以如果哈希中的元素个数比较少,使用ziplist存储,如果hash中元素个数比较多,使用hashtable来存储。
且如果field-value中value都比较短,使用ziplist存储hash,如果某个value的长度过长,也会转换成hashtable存储hash。

通过修改redis配置文件redis.conf中的配置项hash-max-ziplist-entries(默认512个),确定hash中的元素个数超过多少时用hashtable存储hash。
通过修改redis配置文件redis.conf中的配置项hash-max-ziplist-value(默认64字节),确定hash中的元素长度超过多少时用hashtable存储hash。

在这里插入图片描述

hash的应用

作为缓存

redis+mysql组成的缓存存储架构:
在这里插入图片描述
假设把最近使用到的数据作为热点数据存储在redis中,
在上面的场景中:
redis做缓存,应用服务器访问数据,先查询Redis,如果redis上数据存在,就直接从redis上取数据交给应用服务器,不继续访问mysql了。如果redis上数据不存在,再读取mysql,把读到的结果返回给应用服务器的同时,把这个数据也写入到redis中。

用伪代码模拟上述场景,理解hash在其中的应用:
redis用key-value组织用户信息,
key是user:uid,value是hash类型。
在这里插入图片描述
用mysql保存用户信息:
在这里插入图片描述

//当用户发来请求时,假设业务根据用户uid获取用户信息:
//业务层
UserInfo getUserInfo(long uid){//先查询redis,假设用户信息保存在"user:uid"对应的键中。String key = "user:"+uid;//从redis中获取对应的值UserInfoMap value = redis命令:hgetall key;//如果缓存命中(hit)if(value != null){//将映射关系还原成对象形式UserInfo userInfo =  利用映射关系构建对象(UserInfoMap value);return userInfo;}//如果缓存没有命中(miss)//从数据库中,根据uid获取用户信息UserInfo userInfo = mysql执行sql语句:select * from user_info where uid = <uid>;//如果表中没有 uid 对应的⽤⼾信息if(userInfo == null){响应404return null;}//将缓存以哈希类型保存redis执行命令:hmset user:userInfo.uid name userInfo.name age userInfo.age city userInfo.city//写入缓存,为了防止数据腐烂(rot),设置过期时间为1 ⼩时(3600 秒)redis执行命令:expire user:userInfo.uid 3600//返回用户信息return userInfo;
}

比较hash类型和关系型数据库存储用户信息的区别:

  1. 哈希类型是稀疏的,而关系型数据库是完全结构化的。例如哈希类型每个键可以有不同的field,而关系型数据库⼀旦添加新的列,所有行都要为其设置值,即使为null。
    在这里插入图片描述
  2. 关系数据库可以做复杂的关系查询,而Redis去模拟关系型复杂查询,例如联表查询、聚合查询等基本不可能,维护成本高。

三种缓存方式对比

  1. 原生字符串类型⸺⸺使用字符串类型,每个属性⼀个键。
    在这里插入图片描述优点:实现简单,针对个别属性变更也很灵活。
    缺点:占用过多的键,内存占用量较⼤,同时用户信息在Redis中比较分散,缺少内聚性,所以这种方案基本没有实⽤性。

  2. 序列化字符串类型,例如JSON格式
    在这里插入图片描述优点:针对总是以整体作为操作的信息比较合适,编程也简单。同时,如果序列化方案选择合适,内存的使用效率很高。
    缺点:本⾝序列化和反序列需要⼀定开销,同时如果总是操作个别属性则非常不灵活。

  3. hash类型
    在这里插入图片描述优点:简单、直观、灵活。尤其是针对信息的局部变更或者获取操作。
    缺点:需要控制哈希在ziplist和hashtable两种内部编码的转换,可能会造成内存的较大消耗。

比较redis用String类型(Json格式)和用hash类型存储用户信息的区别:

如果用String(JSON)的格式来表示UserInfo,从redis里取出的数据要先通过JSON反序列化转换成对象,从mysql取出的数据要先通过JSON序列化转换成JSON格式。

但是如果用hash类型保存UserInfo,就不用上面两个格外的步骤。且用field表示对象的每个属性,还可以非常方便的修改/获取任何一个属性的值。
当然用hash类型保存UserInfo也有缺点,使用hash类型需要控制hash在ziplist和hashtable两种内部编码的转换,这可能会造成内存的较大消耗。(用空间换时间)

高内聚低耦合

内聚和耦合是衡量代码好坏的标准之一。好的代码应该是高内聚低耦合的。

高内聚:内聚是用来衡量一个模块内部各个元素(如函数、类的方法等)之间的功能相关性和紧密程度的。高内聚意味着模块内的各个部分在功能上高度相关,共同协作完成一个明确的任务。相反,低内聚则表示模块内的各个部分功能不相关或关系松散。
比如上面提到的,把一个用户的所有信息放到hash中一个key中,就是高内聚代码。

低耦合:耦合指的是两个代码/模块之间的关联关系,好的代码追求的是低耦合。模块之间耦合度越高,模块之间越容易相互影响。
比如在分布式系统中引入消息队列就是一个低耦合应用的例子:
假设在一个分布式系统中,A服务器直接调用B服务器,A给B发送请求,B处理请求返回响应给A,此时A和B之间的耦合度是比较大的。
但如果在A和B之间引入消息队列,此时A,消息队列,B三者构成生产者消费者模型,A把请求发给消息队列,B再从消息队列中获取请求,这种情况下如果A出现问题,牵连到B的可能性就很小,A和B之间互连程度降低,即降低了A和B之间的耦合度。


下次见~
在这里插入图片描述

相关文章:

【Redis_Day6】Hash类型

【Redis_Day6】Hash类型 Hash类型操作hash的命令hset&#xff1a;设置hash中指定的字段&#xff08;field&#xff09;的值&#xff08;value&#xff09;hsetnx&#xff1a;想hash中添加字段并设置值hget&#xff1a;获取hash中指定字段的值hexists&#xff1a;判断hash中是否…...

[开源] SafeLine 好用的Web 应用防火墙(WAF)

SafeLine&#xff0c;中文名 “雷池”&#xff0c;是一款简单好用, 效果突出的 Web 应用防火墙(WAF)&#xff0c;可以保护 Web 服务不受黑客攻击 一、简介 雷池通过过滤和监控 Web 应用与互联网之间的 HTTP 流量来保护 Web 服务。可以保护 Web 服务免受 SQL 注入、XSS、 代码注…...

40分钟学 Go 语言高并发:Select多路复用

Select多路复用 学习目标 知识点掌握程度应用场景select实现原理深入理解底层机制channel通信和多路选择超时处理掌握超时控制方法避免阻塞和资源浪费优先级控制理解优先级实现处理多个channel的顺序性能考虑了解性能优化点高并发场景优化 1. Select实现原理 让我们通过一个…...

candence: 如何快速设置SUBCLASS 的颜色

如何快速设置SUBCLASS 的颜色 一、一般操作 正常情况下修改SUBCLASS&#xff0c;需要如下步骤进行设置&#xff1a; 二、快速操作 右键&#xff0c;选择一个颜色即可...

FinalShell进行前端项目部署及nginx配置

首先需要准备服务器(阿里云、腾讯云都可)与域名&#xff1b; 示例为阿里云服务器&#xff1b; 1.进行FinalShell下载 下载官网 https://www.hostbuf.com/ 2.下载完毕后 配置FinalShell ssh ​ 名称自定义即可&#xff01; 2-1 提示连接成功 ​ 3.首先检查nginx是否下载 …...

神经网络(系统性学习一):入门篇——简介、发展历程、应用领域、基本概念、超参数调优、网络类型分类

相关文章&#xff1a; 神经网络中常用的激活函数 神经网络简介 神经网络&#xff08;Neural Networks&#xff09;是受生物神经系统启发而设计的数学模型&#xff0c;用于模拟人类大脑处理信息的方式。它由大量的节点&#xff08;或称为“神经元”&#xff09;组成&#xff0…...

用nextjs开发时遇到的问题

这几天已经基本把node后端的接口全部写完了&#xff0c;在前端开发时考虑时博客视频类型&#xff0c;考虑了ssr&#xff0c;于是选用了nextJs&#xff0c;用的是nextUi,tailwincss,目前碰到两个比较难受的事情。 1.nextUI个别组件无法在服务器段渲染 目前简单的解决方法&…...

微前端基础知识入门篇(二)

概述 在上一篇介绍了一些微前端的基础知识,详见微前端基础知识入门篇(一)。本文主要介绍qiankun微前端框架的实战入门内容。 qiankun微前端实践 通过Vite脚手架分别创建三个程序,主应用A为:vite+vue3+ts,两个微应用分别为B:vite+vue3+ts;C:vite+React+ts。因为qiankun的…...

自然语言处理:第六十五章 MinerU 开源PDF文档解析方案

本人项目地址大全&#xff1a;Victor94-king/NLP__ManVictor: CSDN of ManVictor 原文地址&#xff1a;MinerU&#xff1a;精准解析PDF文档的开源解决方案 论文链接&#xff1a;MinerU: An Open-Source Solution for Precise Document Content Extraction git地址&#xff1…...

Arcpy 多线程批量重采样脚本

Arcpy 多线程批量重采样脚本 import arcpy import os import multiprocessingdef resample_tifs(input_folder, output_folder, cell_size0.05, resampling_type"BILINEAR"):"""将指定文件夹下的所有 TIFF 文件重采样到指定分辨率&#xff0c;并输出…...

python 画图例子

目录 多组折线图点坐标的折线图 多组折线图 数据: 第1行为x轴标签第2/3/…行等为数据,其中第一列为标签&#xff0c;后面为y值 图片: 代码: import matplotlib.pyplot as plt# 原始数据字符串 # 第1行为x轴标签 # 第2/3/...行等为数据,其中第一列为标签&#xff0c;后面…...

Win11 22H2/23H2系统11月可选更新KB5046732发布!

系统之家11月22日报道&#xff0c;微软针对Win11 22H2/23H2版本推送了2024年11月最新可选更新补丁KB5046732&#xff0c;更新后&#xff0c;系统版本号升至22621.4541和22631.4541。本次更新后系统托盘能够显示缩短的日期和时间&#xff0c;文件资源管理器窗口很小时搜索框被切…...

【STM32】MPU6050初始化常用寄存器说明及示例代码

一、MPU6050常用配置寄存器 1、电源管理寄存器1&#xff08; PWR_MGMT_1 &#xff09; 此寄存器允许用户配置电源模式和时钟源。 DEVICE_RESET &#xff1a;用于控制复位的比特位。设置为1时复位 MPU6050&#xff0c;内部寄存器恢复为默认值&#xff0c;复位结束…...

深度学习中的mAP

在深度学习中&#xff0c;mAP是指平均精度均值(mean Average Precision)&#xff0c;它是深度学习中评价模型好坏的一种指标(metric)&#xff0c;特别是在目标检测中。 精确率和召回率的概念&#xff1a; (1).精确率(Precision)&#xff1a;预测阳性结果中实际正确的比例(TP / …...

Redis设计与实现 学习笔记 第二十章 Lua脚本

Redis从2.6版本引入对Lua脚本的支持&#xff0c;通过在服务器中嵌入Lua环境&#xff0c;Redis客户端可以使用Lua脚本&#xff0c;直接在服务器端原子地执行多个Redis命令。 其中EVAL命令可以直接对输入的脚本进行求值&#xff1a; 而使用EVALSHA命令则可以根据脚本的SHA1校验…...

大模型(LLMs)推理篇

大模型&#xff08;LLMs&#xff09;推理篇 1. 为什么大模型推理时显存涨的那么多还一直占着&#xff1f; 首先&#xff0c;序列太长了&#xff0c;有很多Q/K/V&#xff1b;其次&#xff0c;因为是逐个预测next token&#xff0c;每次要缓存K/V加速解码。 大模型在gpu和cpu上…...

Leetcode 412. Fizz Buzz

Problem Given an integer n, return a string array answer (1-indexed) where: answer[i] “FizzBuzz” if i is divisible by 3 and 5.answer[i] “Fizz” if i is divisible by 3.answer[i] “Buzz” if i is divisible by 5.answer[i] i (as a string) if none of t…...

双因子认证:统一运维平台安全管理策略

01双因子认证概述 双因子认证&#xff08;Two-Factor Authentication&#xff0c;简称2FA&#xff09;是一种身份验证机制&#xff0c;它要求用户提供两种不同类型的证据来证明自己的身份。这通常包括用户所知道的&#xff08;如密码&#xff09;、用户所拥有的&#xff08;如…...

CMake笔记:install(TARGETS target,...)无法安装的Debug/lib下

1. 问题描述 按如下CMake代码&#xff0c;无法将lib文件安装到Debug/lib或Release/lib目录下&#xff0c;始终安装在CMAKE_INSTALL_PREFIX/lib下。 install(TARGETS targetCONFIGURATIONS DebugLIBRARY DESTINATION Debug/lib) install(TARGETS targetCONFIGURATIONS Release…...

使用ENSP实现NAT

一、项目拓扑 二、项目实现 1.路由器AR1配置 进入系统试图 sys将路由器命名为R1 sysname R1关闭信息中心 undo info-center enable进入g0/0/0接口 int g0/0/0将g0/0/0接口IP地址配置为12.12.12.1/30 ip address 12.12.12.1 30进入e0/0/1接口 int g0/0/1将g0/0/1接口IP地址配置…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下&#xff0c;卢森堡罗伯特舒曼医院&#xff08;the Robert Schuman Hospitals, HRS&#xff09;凭借在无菌制剂生产流程中引入增强现实技术&#xff08;AR&#xff09;创新项目&#xff0c;荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...

push [特殊字符] present

push &#x1f19a; present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中&#xff0c;push 和 present 是两种不同的视图控制器切换方式&#xff0c;它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解&#xff0c;涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容&#xff0c;并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念&#xff08;ACID&#xff09; 事务是…...