Redis Hash数据类型

Redis Hash数据类型

几乎所有的主流编程语言都提供了哈希(hash)类型,它们的叫法可能是哈希、字典、关联数组、映射。在 Redis 中,哈希类型是指值本身又是一个键值对结构,形如key = “key”,value = {ffield1, value1 }, … {fieldN, valueN } },Redis 键值对和哈希类型二者的关系可以用下图来表示。

字符串和哈希类型对比:

在这里插入图片描述

哈希类型中的映射关系通常称为 field-value,用于区分 Redis 整体的键值对(key-value) ,注意这里的 value 是指 field 对应的值,不是键 (key) 对应的值,请注意 value 在不同上下文的作用。

命令

hset和hget

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

语法

HSET key field value [field value ...]

时间复杂度:插入一组 field 为 O(1),插入 N 组 field 为 O(N)

返回值:添加的字段的个数。 如果当前字段已经存在,此时hset相当于更新,则返回0

示例

redis> hset myhash field1 "Hello"
(integer) 1
redis> hget myhash field1
"Hello"

redis> hset myhash field1 hello field2 world
(integer) 2

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

语法

HGET key field

时间复杂度:O(1)

返回值:字段对应的值或者nilo

示例:

redis> hset myhash field1 "foo"
(integer) 1
redis> hget myhash field1
"foo"
redis> hget myhash field2
(nil)

hexists

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

语法

HEXISTS key field

时间复杂度:O(1)

返回值:1 表示存在,0 表示不存在。

示例

redis> hset myhash field1 "foo"
(integer) 1
redis> hexists myhash field1
(integer) 1
redis> hexists myhash field2
(integer) 0

hdel

删除hash中指定的字段。

语法

HDEL key field [field ...]

时间复杂度:删除⼀个元素为 O(1) 删除 N 个元素为 O(N).

返回值:本次操作删除的字段个数。

示例

redis> hset myhash field1 "foo"
(integer) 1
redis> hdel myhash field1
(integer) 1
redis> hexists myhash filed
(integer) 0
redis> hdel myhash field2
(integer) 0

hkeys

获取hash中的所有字段。

语法

HKEYS key

时间复杂度:O(N), N 为 field 的个数.。

返回值:字段列表。

示例

redis> hset myhash field1 "Hello"
(integer) 1
redis> hset myhash field2 "World"
(integer) 1
redis> hkeys myhash
1) "field1"
2) "field2"

hvals

获取hash中的所有的值。

语法

HVALS key

时间复杂度:O(N), N 为 field 的个数。

返回值:所有的值。

示例

redis> hset myhash field1 "Hello"
(integer) 1
redis> hset myhash field2 "World"
(integer) 1
redis> hvals myhash
1) "Hello"
2) "World"

hgetall

获取 hash 中的所有字段以及对应的值。

语法

HGETALL key

时间复杂度:O(N), N 为 field 的个数

返回值:字段和对应的值。

示例

redis> hset myhash field1 "Hello"
(integer) 1
redis> hset myhash field2 "World"
(integer) 1
redis> hgetall myhash
1) "field1"
2) "Hello"
3) "field2"
4) "World"

hmget

⼀次获取hash中多个字段的值。

语法

HMGET key field [field ...]

时间复杂度:只查询⼀个元素为 O(1), 查询多个元素为 O(N), N 为查询元素个数。

返回值:字段对应的值或者 nil。

示例

redis> hset myhash field1 "Hello"
(integer) 1
redis> hset myhash field2 "World"
(integer) 1
redis> hmget myhash field1 field2 nofield
1) "Hello"
2) "World"
3) (nil)

在使用 HGETALL 时,如果哈希元素个数比较多,会存在阻塞 Redis 的可能。如果开友人员只需要获取部分 field,可以使用 HMGET,如果一定要获取全部field,可以尝试使用 HSCAN 命令,该命令采用渐进式遍历哈希类型。

hlen

获取 hash 中的所有字段(key)的个数。

语法

HLEN key

时间复杂度:O(1)

返回值:字段个数。

示例

redis> hset myhash field1 "Hello"
(integer) 1
redis> hset myhash field2 "World"
(integer) 1
redis> hlen myhash
(integer) 2

hsetnx

在字段不存在的情况下,设置 hash 中的字段和值。

语法

HSETNX key field value

时间复杂度:O(1)

返回值:1 表示设置成功,0 表示失败。

示例

redis> hsetnx myhash field "Hello"
(integer) 1
redis> hsetnx myhash field "World"
(integer) 0
redis> hget myhash field
"Hello"

hincrby

将hash中字段对应的数值添加指定的值。

语法

HINCRBY key field increment

时间复杂度:O(1)

返回值:该字段变化之后的值。

示例

redis> hset myhash field 5
(integer) 1
redis> hincrby myhash field 1
(integer) 6
redis> hincrby myhash field -1
(integer) 5
redis> hincrby myhash field -10
(integer) -5

hincrbyfloat

hincrby的浮点数版本。

语法:

HINCRBYFLOAT key field increment

时间复杂度:O(1)

返回值:该字段变化之后的值。

示例

redis> hset mykey field 10.50
(integer) 1
redis> hincrbyfloat mykey field 0.1
"10.6"
redis> hincrbyfloat mykey field -5
"5.6"
redis> hset mykey field 5.0e3   #5000
(integer) 0
redis> HINCRBYFLOAT mykey field 2.0e2   #200
"5200"

内部编码

哈希的内部编码有两种:

  • ziplist(压缩列表):当哈希类型元素个数小于 hash-max-ziplist-entries 配置(默认512个)、同时所有值都小于 hash-max-ziplist-value 配置默认64字节)时,Redis 会使用 ziplist 作为哈希的内部实现,ziplist 使用更加紧凑的结构实现多个元素的连续存储,所以在节省内存方面比 hashtable 更加优秀。
  • hashtable (哈希表)︰当哈希类型无法满足 ziplist 的条件时,Redis 会使用 hashtable 作为哈希的内部实现,因为此时 ziplist 的读写效率会下降,而 hashtable 的读写时间复杂度为O(1)。

下面的示例演示了哈希类型的内部编码,以及响应的变化。

1)当 field 个数比较少且没有大的 value 时,内部编码为 ziplist:

127.0.0.1:6379> hmset hashkey f1 v1 f2 v2
OK
127.0.0.1:6379> object encoding hashkey
"ziplist"

2)当有 value 大于 64 字节时,内部编码会转换为 hashtable:

127.0.0.1:6379> hset hashkey f3 6666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
(integer) 1
127.0.0.1:6379> object encoding hashkey
"hashtable"

3)当 field 个数超过 512 时,内部编码也会转换为 hashtable

127.0.0.1:6379> hmset hashkey f1 v1 f2 v2 f3 v3 ... 省略 ... f513 v513
OK
127.0.0.1:6379> object encoding hashkey
"hashtable"

使用场景

图"关系型数据表保存用户信息"为关系型数据表记录的两条用户信息,用户的属性表现为表的列,每条用户信息表现为行。如果映射关系表示这两个用户信息,则如图"映射关系表示用户信息"所示。

关系型数据表保存用户信息

在这里插入图片描述

映射关系表示用户信息

在这里插入图片描述

相比于使用Json格式的字符串缓存用户信息,哈希类型变得更加直观,并且在更新操作上变得更灵活。可以将每个用户的id定义为键后缀,多对field-value对应用户的各个属性,类似如下伪代码:

UserInfo getUserInfo(long uid) {
    // 根据 uid 得到 Redis 的键
    String key = "user:" + uid;

    // 尝试从 Redis 中获取对应的值
    userInfoMap = Redis 执⾏命令:hgetall key;

    // 如果缓存命中(hit)
    if (value != null) {
        // 将映射关系还原为对象形式
        UserInfo userInfo = 利⽤映射关系构建对象(userInfoMap);
        return userInfo;
    }

    // 如果缓存未命中(miss)
    // 从数据库中,根据 uid 获取⽤⼾信息
    UserInfo userInfo = MySQL 执⾏ SQL:select *from user_info where uid = <uid>

            // 如果表中没有 uid 对应的⽤⼾信息
    if (userInfo == null) {
        响应 404 
        return null;
    }

    // 将缓存以哈希类型保存
    Redis 执⾏命令:hmset key name userInfo.name age userInfo.age city userInfo.c

    // 写⼊缓存,为了防⽌数据腐烂(rot),设置过期时间为 1 ⼩时(3600 秒)
    Redis 执⾏命令:expire key 3600

    // 返回⽤⼾信息
    return userInfo;
}

但是需要注意的是哈希类型和关系型数据库有两点不同之处:

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

缓存方式对比

  1. 原生字符串类型⸺使用字符串类型,每个属性⼀个键。
set user:1:name James
set user:1:age 23
set user:1:city Beijing
  • 优点:实现简单,针对个别属性变更也很灵活。
  • 缺点∶占用过多的键,内存占用量较大,同时用户信息在Redis中比较分散,缺少内聚性,所以这种方案基本没有实用性。
  1. 序列化字符串类型,例如 JSON 格式
set user:1 经过序列化后的⽤⼾对象字符串
  • 优点∶针对总是以整体作为操作的信息比较合适,编程也简单。同时,如果序列化方案选择合适,内存的使用效率很高。
  • 缺点:本身序列化和反序列需要一定开销,同时如果总是操作个别属性则非常不灵活。
  1. 哈希类型
hmset user:1 name James age 23 city Beijing
  • 优点:简单、直观、灵活。尤其是针对信息的局部变更或者获取操作。
set user:1:name James
set user:1:age 23
set user:1:city Beijing
  • 优点:实现简单,针对个别属性变更也很灵活。
  • 缺点∶占用过多的键,内存占用量较大,同时用户信息在Redis中比较分散,缺少内聚性,所以这种方案基本没有实用性。
  1. 序列化字符串类型,例如 JSON 格式
set user:1 经过序列化后的⽤⼾对象字符串
  • 优点∶针对总是以整体作为操作的信息比较合适,编程也简单。同时,如果序列化方案选择合适,内存的使用效率很高。
  • 缺点:本身序列化和反序列需要一定开销,同时如果总是操作个别属性则非常不灵活。
  1. 哈希类型
hmset user:1 name James age 23 city Beijing
  • 优点:简单、直观、灵活。尤其是针对信息的局部变更或者获取操作。
  • 缺点:需要控制哈希在ziplist和 hashtable两种内部编码的转换,可能会造成内存的较大消耗。

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

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

相关文章

HTTP 缓存机制

一、强制缓存 只要浏览器判断缓存没有过期&#xff0c;则直接使用浏览器的本地缓存而无需再请求服务器。 强制缓存是利用下面这两个 HTTP 响应头部&#xff08;Response Header&#xff09;字段实现的&#xff0c;它们都用来表示资源在客户端缓存的有效期&#xff1a; Cache…

对抗神经网络 CGAN实战详解 完整数据代码可直接运行

代码视频讲解: 中文核心项目:对抗神经网络 CGAN实战详解 完整代码数据可直接运行_哔哩哔哩_bilibili 运行图: 完整代码: from keras.layers import Input, Dense, Reshape, Flatten, Dropout, multiply from keras.layers import BatchNormalization, Activation, Embedd…

单片机系统

我们来看单片机 的例子&#xff0c;读者可能会担心单片机&#xff08;又称MCU&#xff0c;或微控制器&#xff09; 过于专业而无法理解。完全没必要&#xff01;在这里我们仅借它谈论一下有关时间的话题&#xff0c;顺带提一下单片机系统的概念。 单片机顾名思义是集成到一个芯…

Java开发中一些重要软件安装配置

Java技术栈中重要过程 1、JavaWeb1、开发工具VsCode的安装和使用2、Tomcat服务器3、nodejs的简介和安装4、Vite创建Vue3工程化项目ViteVue3项目的创建、启动、停止ViteVue3项目的目录结构 5、Maven安装和配置 1、JavaWeb 1、开发工具VsCode的安装和使用 1 安装过程 安装过程比…

IDEA插件:Apipost-Helper

Apipost-Helper是由Apipost推出的IDEA插件&#xff0c;写完接口可以进行快速调试&#xff0c;且支持搜索接口、根据method跳转接口&#xff0c;还支持生成标准的API文档&#xff0c;注意&#xff1a;这些操作都可以在代码编辑器内独立完成&#xff0c;非常好用&#xff01;这里…

RocketMQ Copilot 一款面向 Apache RocketMQ 的智能辅助运维系统

一、RocketMQ简介 ocketMQ是阿里巴巴研发的一款分布式消息中间件&#xff0c;后开源给Apache基金会&#xff0c;成为apache的顶级开源项目。它具有高性能、高可靠、高实时和分布式的特点。RocketMQ主要应用于解决应用耦合&#xff0c;消息分发&#xff0c;流量削锋等问题。 R…

Python神器:快速删除文本文件中指定行的方法

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 1. 简介 文件操作是编程中的重要方面。Python作为强大的编程语言&#xff0c;提供了处理文件的能力。删除特定行是文件处理中常见的需求。 2. 打开文件和读取内容 当打开文件并读取其内容时&#xff0c;open(…

全球与中国仿制药市场:增长趋势、竞争格局与前景展望

仿制药是指在剂型、功效、给药方法、品质、性能特征、用途等方面与原厂药相似并已获得原厂药上市许可的药品。仿制药的价格低于品牌药。糖尿病、癌症和心血管疾病等慢性疾病的快速成长推动了仿制药市场的成长。此外&#xff0c;仿制药的实惠价格以及最新产品的批准和推出也有助…

css 修改滚动条样式,解决Windows浏览器中滚动条不美观问题

Windows环境中的浏览器中滚动条默认是直接显示了&#xff0c;不管光标是否进入该区域&#xff0c;这样就很不美观&#xff0c;如下图&#xff1a; 之前样式为 .well {display: block;background-color: #f2f2f2;border: 1px solid #ccc;margin: 5px;width: calc(100% - 12px);h…

在Matlab里安装gurobipy怎么安装教程

在Matlab 里安装gurobipy 先在CMD里激活&#xff0c; 然后添加系统环境变量 GRB_LICENSE_FILEC:\gurobi10.2\gurobi.lic 然后输入 addpath(D:\gurobi1003\win64\matlab) addpath(C:\gurobi1003\win64\matlab) addpath(C:\gurobi1002\win64\matlab) C:\gurobi1003\win64\m…

vue自定义指令:指定文字高亮

vue自定义指令&#xff1a;指定文字高亮 自定义指令 除了核心功能默认内置的指令 (v-model 和 v-show)&#xff0c;Vue 也允许注册自定义指令。注意&#xff0c;在 Vue2.0 中&#xff0c;代码复用和抽象的主要形式是组件。然而&#xff0c;有的情况下&#xff0c;你仍然需要对…

市场缺口投资者应该怎么做? 昂首资本一招就能盈利

当在市场交易分析中&#xff0c;投资者发现市场缺口或者价格缺口的时候&#xff0c; 昂首资本问各位投资者应该怎么才能抓住机会盈利一波。 其实在技术分析中的这个术语指的是&#xff1a;前一根棒线的收盘价和下一根棒线的开盘价之间有差距的情况。例如&#xff0c;当做市商将…

idea类和方法模版

类模版 修改目标位置 class #if (${PACKAGE_NAME} && ${PACKAGE_NAME} ! "")package ${PACKAGE_NAME};#end #parse("File Header.java")/*** ${Description}* author whc ${YEAR}/${MONTH}/${DAY}* version v1.0 */public class ${NAME} { }inte…

利用Linux中的iptables进行网络代理配置

作为资深爬虫技术员&#xff0c;爬虫需要代理IP池介入这是众所周知的。今天我将用我毕生所学&#xff0c;谈谈linux中使用iptables工具来进行网络配置&#xff0c;并通过linux系统创建属于自己的ip库池&#xff0c;如有错误望各位大佬指正。 我们知道&#xff0c;在Linux中&am…

JFrog----SBOM清单包含哪些:软件透明度的关键

文章目录 SBOM清单包含哪些&#xff1a;软件透明度的关键引言SBOM清单的重要性SBOM清单包含的核心内容SBOM的创建和管理结论 软件物料清单&#xff08;SBOM&#xff09;是一个在软件供应链安全中越来越重要的组成部分。它基本上是一份清单&#xff0c;详细列出了在特定软件产品…

Node-red

Node-Red 什么是Node-redNode-red的特点 Node-red的Windows安装安装Node.js安装包下载安装包安装安装检查 安装Node-red安装Note-red运行Note-red 什么是Node-red Node-RED 是一种编程工具&#xff0c;用于以新颖有趣的方式将硬件设备、API 和在线服务连接在一起。 Node-RED 是…

2023年12月4日:多继承

代码 #include <iostream>using namespace std;class Sofa { private:string sit;int *len; public:Sofa(){cout << "Sofa::无参构造函数" << endl;}Sofa(string sit,int len):sit(sit),len(new int(len)){cout << "Sofa::有参构造函数…

3DMM模型

目录 BFMBFM_200901_MorphableModel.matexp_pca.bintopology_info.npyexp_info.npy BFM BFM_2009 01_MorphableModel.mat from scipy.io import loadmat original_BFM loadmat("01_MorphableModel.mat") # dict_keys: [__header__, __version__, __globals__, # …

Python实现交易策略评价指标-夏普比率

1.夏普比率的定义 在投资的过程中&#xff0c;仅关注策略的收益率是不够的&#xff0c;同时还需要关注承受的风险&#xff0c;也就是收益风险比。 夏普比率正是这样一个指标&#xff0c;它表示承担单位的风险会产生多少超额收益。用数学公式描述就是&#xff1a; S h a r p R…

【Qt开发流程】之事件过滤器及sendEvent和postEvent

描述 事件过滤器(Event Filter)是Qt中一个强大的事件处理机制&#xff0c;它可以在对象接收到事件之前截获事件&#xff0c;并进行自定义处理。事件过滤器可以在不修改对象自身代码的前提下&#xff0c;对其进行事件处理和拦截。 事件过滤器的使用过程如下&#xff1a; 创建一…
最新文章