【redis】Redis数据类型(二)Hash类型

目录

  • Hash类型介绍
    • 特性
    • hash 的内部编码方式/底层结构
      • hashtable
      • ziplist
      • listpack
    • 适用场景
      • 举例
    • 常用命令
      • hset
        • 示例
      • hsetnx
        • 示例:
      • hmset
        • 示例
      • hget
        • 示例
      • hmget
        • 示例
      • hgetall
        • 示例
      • hdel
        • 示例
      • hlen
        • 示例
      • hexists
        • 示例
      • hincrby
        • 示例
      • hincrbyfloat
        • 示例
      • hkeys
        • 示例
      • hvals
        • 示例

Hash类型介绍

Hash 类型是一种键值对集合,这种数据类型适合用于存储对象

特性

  • 键值对集合:Hash 类型可以存储多个键值对,每个键都有一个对应的值。
  • 二进制安全:Hash 类型的键和值都是二进制安全的,这意味着它们可以包含任何数据,包括二进制数据。
  • 大容量:单个 Hash 类型可以存储超过 4 亿个键值对。
  • 高效的查找速度:无论 Hash 中存储了多少数据,查找某个键的速度都非常快。

hash 的内部编码方式/底层结构

Redis 的 Hash 类型会根据实际情况在压缩列表(ziplist)和散列表(hashtable)之间进行切换,这主要取决于两个配置参数:hash-max-ziplist-entries 和 hash-max-ziplist-value。

  • hash-max-ziplist-entries:这个参数用于设置压缩列表可以存储的最大节点数量。如果一个 Hash 类型的元素数量超过这个值,那么就会从压缩列表切换到散列表。默认值为 512;
  • hash-max-ziplist-value:这个参数用于设置压缩列表中每个节点的最大值大小(以字节为单位)。如果一个 Hash 类型的任何元素的大小超过这个值,那么就会从压缩列表切换到散列表。默认值为 64。

hashtable

  • 最基本的哈希表(不是 java 标准库中的 HashTable),redis 内部对哈希表的实现方式和 java 中的哈希表可能不太一样,但是整体思想都是一样的;时间上复杂度O(1),但是空间上会有一定的浪费(hash 是一个数组,数组上有些位置有元素,有些位置没有元素).
  • 当 Hash 类型存储的字段和值的数量较多,或者字段和值的字符串长度较长时,Redis 会选择使用散列表作为底层实现。散列表是一种常见的键值对映射结构,它通过一个散列函数将键映射到一个桶中,然后在桶中进行查找。这种方式的优点是查找和修改数据的性能较高,但是占用的内存也较多。
  • Redis 的散列表(hash table)是一种常见的键值对映射结构,它通过一个散列函数将键映射到一个桶中,然后在桶中进行查找。Redis 的散列表使用链表法解决哈希冲突,即当多个键映射到同一个桶时,将它们存储在同一个链表中

ziplist

压缩列表,当哈希表里的元素比较少的时候,就优化成了 ziplist 了,在Redis7.0之前使用,特点是内存占用教少,能够节省空间,但是读写元素的速度比较慢;

  • 如果 hash 中的元素比较少,使用 ziplist 表示. 元素比较多的时候使用 hashtable 表示.
  • 每个 value 值的长度都比较短的,使用 ziplist 表示. 如果某个 value 长度太长,也会转化成 hashtable.
  • 压缩的本质就是对数据进行重新编码,不同的数据有不同的特点,结合这些特点,重新编码后,就能够缩小体积
  • 例如 abbcccdddd 重新编码就变成了 1a2b3c4d.

listpack

紧凑列表,在Redis7.0版本之后取代了ziplist,同样也是hash到达一定阀值后转换为hashtable。

适用场景

  1. 存储对象:Hash 类型可以存储多个键值对,非常适合用于存储对象。例如,你可以使用 Hash 类型存储用户的信息,如用户名、密码、邮箱等;
  2. 数据分析:你可以使用 Hash 类型存储各种统计数据,例如用户的行为数据,然后进行数据分析;
  3. 社交网络:在社交网络应用中,你可以使用 Hash 类型存储用户的朋友列表、粉丝列表等
  4. 购物车场景的使用。使用用户ID作为key,商品ID作为field,商品数量或规格等信息作为value,便于快速增删改查购物车中的商品项
  5. 缓存配置信息:应用程序的配置信息,如各种设置参数,可以集中存储在Hash中,方便统一管理和实时更新
  6. 权限列表管理: 用Hash存储用户的权限信息,key为用户ID,field表示权限标识符,value为权限状态(如允许/禁止)。
  7. 进度存储:如小说阅读进度、视频播放进度等场景,key可以是用户ID+资源ID组合,field为资源唯一标识,value为对应的进度值。
  8. 关系模型数据建模:当需要在Redis中模拟关系型数据库中的一对多或者多对多关系时,Hash可以作为一个轻量级的解决方案,简化数据结构设计
  9. 计数器集合:当需要统计一组相关联的数据项的不同维度计数时,可以使用Hash存储每个维度的计数值。

举例

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

常用命令

命令描述
hset key field valuefiled的不存在新增并返回1,如果filed已经存在就覆盖更新并返回0
hsetnx key field value如果filed不存在则设置值为字符串value并返回1,否则不做任何操作返回0
hgetall key field获取这个key的所有field-value,返回结果为数组
hdel key field删除field的value,删除成功返回1,删除失败返回0
hdel key删除key的所有field-value,删除成功返回1,删除失败返回0
hmset k1 f1 v1 k2 f2 v2 …批量操作一次性新增或更新多个field
hmget f1 f2 …批量操作一次性获取多个field的value
hexists key field判断field是否存在,存在返回1,否侧返回0
hsetnx key field valuefield不存在则设置值,否则不操作
hvals key获取hash结构的所有值

hset

  • 语法:hset key field value
  • 解释:
    • 将哈希表 key 中的域 field 的值设为 value 。
    • 如果 key 不存在,一个新的哈希表被创建并进行 HSET 操作。
    • 如果域 field 已经存在于哈希表中,旧值将被覆盖
  • 时间复杂度:O(1)
  • 返回值:
    • 如果 field 是哈希表中的一个新建域,并且值设置成功,返回 1 。
    • 如果哈希表中域 field 已经存在且旧值已被新值覆盖,返回 0 。
示例
127.0.0.1:6379[3]> hset mywebsite csdn "zhoujl.blog.csdn.net"
(integer) 1
127.0.0.1:6379[3]> hset mywebsite csdn "https://zhoujl.blog.csdn.net"
(integer) 0
127.0.0.1:6379[3]>

hsetnx

  • 语法:hsetnx key field value
  • 解释:
    • 将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在。
    • 若域 field 已经存在,该操作无效。
    • 如果 key 不存在,一个新哈希表被创建并执行 HSETNX 命令。
  • 时间复杂度:O(1)
  • 返回值:
    • 设置成功,返回 1 。
    • 如果给定域已经存在且没有操作被执行,返回 0 。
示例:
127.0.0.1:6379[3]> hsetnx user username admin
(integer) 1
127.0.0.1:6379[3]> hsetnx user userage 20
(integer) 1
127.0.0.1:6379[3]> hsetnx user username root
(integer) 0
127.0.0.1:6379[3]>

hmset

  • 语法:hmset key field value [field value …]
  • 解释:
    • 同时将多个 field-value (域-值)对设置到哈希表 key 中。
    • 此命令会覆盖哈希表中已存在的域。
    • 如果 key 不存在,一个空哈希表被创建并执行 HMSET 操作。
  • 复杂度:O(N), N 为 field-value 对的数量。
  • 返回值类型:
    • 如果命令执行成功,返回 OK 。
    • 当 key 不是哈希表(hash)类型时,返回一个错误。
示例
127.0.0.1:6379[3]> hmset role roleId 1 roleName admin
OK
127.0.0.1:6379[3]> hget role roleId
"1"
127.0.0.1:6379[3]> hget role roleName
"admin"
127.0.0.1:6379[3]>

hget

  • 语法:hget key field
  • 解释:返回哈希表 key 中给定域 field 的值
  • 时间复杂度:O(1)
  • 返回值:
    • 给定域的值。
    • 当给定域不存在或是给定 key 不存在时,返回 nil 。
示例
127.0.0.1:6379[3]> hset site redis redis.com
(integer) 1
127.0.0.1:6379[3]> hget site redis
"redis.com"
127.0.0.1:6379[3]> hget site mysql
(nil)
127.0.0.1:6379[3]>

hmget

  • 语法:hmget key field [field …]
  • 解释:
    • 返回哈希表 key 中,一个或多个给定域的值。
    • 如果给定的域不存在于哈希表,那么返回一个 nil 值。
    • 因为不存在的 key 被当作一个空哈希表来处理,所以对一个不存在的 key 进行 HMGET 操作将返回一个只带有 nil 值的表。
  • 时间复杂度:O(N), N 为给定域的数量。
  • 返回值:一个包含多个给定域的关联值的表,表值的排列顺序和给定域参数的请求顺序一样
示例
127.0.0.1:6379[3]> hmset pet dog anpei cat mimi
OK
127.0.0.1:6379[3]> hmget pet dog cat penguin
1) "anpei"
2) "mimi"
3) (nil)
127.0.0.1:6379[3]>

hgetall

  • 语法:hgetall key
  • 解释
    • 返回哈希表 key 中,所有的域和值。
    • 在返回值里,紧跟每个域名(field name)之后是域的值(value),所以返回值的长度是哈希表大小的两倍。
  • 时间复杂度:O(N), N 为哈希表的大小。
  • 返回值:
    • 以列表形式返回哈希表的域和域的值。
    • 若 key 不存在,返回空列表。
示例
127.0.0.1:6379[3]> hset city zz zhengzhou
(integer) 1
127.0.0.1:6379[3]> hset city hz hangzhou
(integer) 1
127.0.0.1:6379[3]> hgetall city
1) "zz"	# 属性/域
2) "zhengzhou" 	# 值
3) "hz"
4) "hangzhou"
127.0.0.1:6379[3]>

hdel

  • 语法:hdel key field [field …]
  • 解释:
    • 删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略。
    • 注:在 Redis2.4 以下的版本里, HDEL 每次只能删除单个域,如果你需要在一个原子时间内删除多个域,请将命令包含在 MULTI / EXEC 块内。
  • 时间复杂度:O(N), N 为要删除的域的数量。
  • 返回值:被成功移除的域的数量,不包括被忽略的域。
示例
127.0.0.1:6379[3]> hgetall city1) "zz"2) "zhengzhou"3) "hz"4) "hangzhou"5) "kf"6) "kaifeng"7) "ly"8) "luoyang"9) "bj"
10) "beijing"
11) "sh"
12) "shanghai"
127.0.0.1:6379[3]> hdel city sh
(integer) 1
127.0.0.1:6379[3]> hdel city hz bj
(integer) 2
127.0.0.1:6379[3]> hgetall city
1) "zz"
2) "zhengzhou"
3) "kf"
4) "kaifeng"
5) "ly"
6) "luoyang"
127.0.0.1:6379[3]>

hlen

  • 语法:hlen key
  • 解释:返回哈希表 key 中域的数量。
  • 时间复杂度:O(1)
  • 返回值:
    • 哈希表中域的数量。
    • 当 key 不存在时,返回 0 。
示例
127.0.0.1:6379[3]> hgetall city
1) "zz"
2) "zhengzhou"
3) "kf"
4) "kaifeng"
5) "ly"
6) "luoyang"
127.0.0.1:6379[3]> hlen city
(integer) 3
127.0.0.1:6379[3]>

hexists

  • 语法:hexists key field
  • 解释:查看哈希表 key 中,给定域 field 是否存在。
  • 时间复杂度:O(1)
  • 返回值:
    • 如果哈希表含有给定域,返回 1 。
    • 如果哈希表不含有给定域,或 key 不存在,返回 0 。
示例
127.0.0.1:6379[3]> hexists city sh
(integer) 0
127.0.0.1:6379[3]> hexists city zz
(integer) 1
127.0.0.1:6379[3]>

hincrby

  • 语法:hincrby key field increment
  • 解释:
    • 为哈希表 key 中的域 field 的值加上增量 increment 。
    • 增量也可以为负数,相当于对给定域进行减法操作。
    • 如果 key 不存在,一个新的哈希表被创建并执行 HINCRBY 命令。
    • 如果域 field 不存在,那么在执行命令前,域的值被初始化为 0 。
    • 对一个储存字符串值的域 field 执行 HINCRBY 命令将造成一个错误。
    • 本操作的值被限制在 64 位(bit)有符号数字表示之内
  • 时间复杂度:O(1)
  • 返回值:执行 HINCRBY 命令之后,哈希表 key 中域 field 的值。
示例
# increment 为正数
127.0.0.1:6379[3]> HEXISTS counter page_view # 对空域进行设置
(integer) 0
127.0.0.1:6379[3]> HINCRBY counter page_view 200
(integer) 200
127.0.0.1:6379[3]> HGET counter page_view
"200"
# increment 为负数
127.0.0.1:6379[3]> HGET counter page_view
"200"
127.0.0.1:6379[3]> HINCRBY counter page_view -50
(integer) 150
127.0.0.1:6379[3]> HGET counter page_view
"150"
# 尝试对字符串值的域执行 HINCRBY 命令
127.0.0.1:6379[3]> HSET myhash string hello,world # 设定一个字符串值
(integer) 1
127.0.0.1:6379[3]> HGET myhash string
"hello,world"
127.0.0.1:6379[3]> HINCRBY myhash string 1 # 命令执行失败,错误。
(error) ERR hash value is not an integer
127.0.0.1:6379[3]> HGET myhash string # 原值不变
"hello,world"

hincrbyfloat

  • 语法:hincrbyfloat key field increment
  • 解释:
    • 为哈希表 key 中的域 field 加上浮点数增量 increment 。
    • 如果哈希表中没有域 field ,那么 HINCRBYFLOAT 会先将域 field 的值设为 0 ,然后再执行加法操作。
    • 如果键 key 不存在,那么 HINCRBYFLOAT 会先创建一个哈希表,再创建域 field ,最后再执行加法操作。
    • 当以下任意一个条件发生时,返回一个错误:
      • 域 field 的值不是字符串类型(因为 redis 中的数字和浮点数都以字符串的形式保存,所以它们都属于字符串类型)
      • 域 field 当前的值或给定的增量 increment 不能解释(parse)为双精度浮点数(double precision floating point number)
    • HINCRBYFLOAT 命令的详细功能和 INCRBYFLOAT 命令类似,请查看 INCRBYFLOAT 命令获取更多相关信息。
  • 时间复杂度:O(1)
  • 返回值:执行加法操作之后 field 域的值。
示例
# 值和增量都是普通小数
127.0.0.1:6379[3]> HSET mykey field 10.50
(integer) 1
127.0.0.1:6379[3]> HINCRBYFLOAT mykey field 0.1
"10.6"
# 值和增量都是指数符号
127.0.0.1:6379[3]> HSET mykey field 5.0e3
(integer) 0
127.0.0.1:6379[3]> HINCRBYFLOAT mykey field 2.0e2
"5200"
# 对不存在的键执行 HINCRBYFLOAT
127.0.0.1:6379[3]> EXISTS price
(integer) 0
127.0.0.1:6379[3]> HINCRBYFLOAT price milk 3.5
"3.5"
127.0.0.1:6379[3]> HGETALL price
1) "milk"
2) "3.5"
# 对不存在的域进行 HINCRBYFLOAT
127.0.0.1:6379[3]> HGETALL price
1) "milk"
2) "3.5"
127.0.0.1:6379[3]> HINCRBYFLOAT price coffee 4.5 # 新增 coffee 域
"4.5"
127.0.0.1:6379[3]> HGETALL price
1) "milk"
2) "3.5"
3) "coffee"
4) "4.5

hkeys

  • 语法:hkeys key
  • 解释:返回哈希表 key 中的所有域。
  • 时间复杂度:O(N), N 为哈希表的大小。
  • 返回值:
    • 一个包含哈希表中所有域的表。
    • 当 key 不存在时,返回一个空表。
示例
# 哈希表非空
127.0.0.1:6379[3]> HMSET website google www.google.com yahoo www.yahoo.com
OK
127.0.0.1:6379[3]> HKEYS website
1) "google"
2) "yahoo"
# 空哈希表/key 不存在
127.0.0.1:6379[3]> EXISTS fake_key
(integer) 0
127.0.0.1:6379[3]> HKEYS fake_key
(empty list or set)

hvals

  • 语法:hvals key
  • 解释:返回哈希表 key 中所有域的值。
  • 时间复杂度:O(N), N 为哈希表的大小。
  • 返回值:
    • 一个包含哈希表中所有值的表。
    • 当 key 不存在时,返回一个空表。
示例
# 非空哈希表
127.0.0.1:6379[3]> HMSET website google www.google.com yahoo www.yahoo.com
OK
127.0.0.1:6379[3]> HVALS website
1) "www.google.com"
2) "www.yahoo.com"
# 空哈希表/不存在的 key
127.0.0.1:6379[3]> EXISTS not_exists
(integer) 0
127.0.0.1:6379[3]> HVALS not_exists
(empty list or set)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

光纤网络电力控制系统设计方案:623-6U CPCI的光纤网络电力控制系统

6U CPCI的光纤网络电力控制系统 一、设备概述 柔性直流输电系统中用于控制与测量的FS系统,适用于风电和太阳能发电的并网快速数值计算和闭环控制,以及与直流输电系统的换流器有关的特殊控制功能,包括门控单元的信号处理。该控制板的最大…

【C++】:手撕红黑树(红黑树的模拟实现)

每日给大家介绍一家公司 如下 接下来我们进入正题 1.红黑树的概念 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树…

2024蓝桥杯CTF--逆向

蓝桥杯付费CT--逆向 题目:RC4题目:happytime总结: 题目:RC4 先查壳,无壳,并且是32位: 用32位的ida打开,直接定位到main函数: 重点关注sub_401005函数,这个应…

SDM模型——建模用户长短期兴趣的Match模型

1. 引言 SDM模型(Sequential Deep Matching Model)是阿里团队在2019年CIKM的一篇paper。模型属于序列召回模型,研究的是如何通过用户的历史行为序列去学习到用户的丰富兴趣。 SDM模型把用户的历史序列根据交互的时间分成了短期和长期两类,然后从短期会…

构建NodeJS库--前端项目的打包发布

1. 前言 学习如何打包发布前端项目,需要学习以下相关知识: package.json 如何初始化配置,以及学习npm配置项; 模块类型type配置, 这是nodejs的package.json的配置main 入口文件的配置 webpack 是一个用于现代 JavaSc…

基于java+springboot+vue实现的个人博客系统(文末源码+Lw)200

摘 要 随着国内市场经济这几十年来的蓬勃发展,突然遇到了从国外传入国内的互联网技术,互联网产业从开始的群众不信任,到现在的离不开,中间经历了很多挫折。本次开发的个人博客系统,有管理员,用户&#xf…

excel一列同乘同一个数

excel一列同乘同一个数 第一种方法(excel本身功能) 在空白区域输入要乘以的数,比如0.5 右键选择复制 选中需要乘以的单元格,选择性粘贴 点击乘,选择确定 删除0.5后也不会改变值 第二种方法(方方格子…

HODL、FUD、FOMO 等其他比特币俚语是什么意思?

作者:Paxful Team 1、FOMO(惧怕错失机会) FOMO 是惧怕错失机会的缩写,可用于日常生活。它指的是当其他人都在谈论比特币时,产生的购买比特币的紧迫感。 2、Shill(不断推广吹捧) Shilling 是指…

上传jar到github仓库,作为maven依赖存储库

记录上传maven依赖包到github仓库问题 利用GitHubPackages作为依赖的存储库踩坑1 仓库地址问题踩坑2 Personal access tokens正确姿势一、创建一个普通仓库,比如我这里是fork的腾讯Shadow到本地。地址是:https://github.com/dhs964057117/Shadow二、生成…

[C++ QT项目实战]----C++ QT系统实现多线程通信

前言 在C QT中,多线程通信原理主要涉及到信号与槽机制和事件循环机制。 1、信号与槽机制: 在QT中,信号与槽是一种用于对象间通信的机制。对象可以通过发送信号来通知其他对象,其他对象通过连接槽来接收信号并进行相应的处…

39岁TVB靓仔小生自曝恋情,曾沦为洗车工如今半年赚足7位数

39岁高钧贤自从2005年参加香港先生选举夺冠后,之后加入TVB拍摄过多套电视剧集,最近更有份参与《逆天奇案2》,日前他回到TVB电视城一厂与冯盈盈宣传剧集,更随即拍摄短片纪录放在网上分享,意外曝光TVB餐厅餐单&#xff0…

MFRC50001T 封装SOP-32 高性能非接触式读写芯片

MFRC50001T是由NXP Semiconductors(恩智浦半导体)生产的一款高性能非接触式读写芯片。这款芯片主要针对13.56 MHz频段的RFID(无线射频识别)和MIFARE Classic协议,支持ISO/IEC 14443 Type A标准的多层应用。MFRC50001T芯…

pve(Proxmox VE)安装i225v网卡驱动

配置pve源 备份原来的源 mv /etc/apt/sources.list /etc/apt/sources.list.bak打开文件 vi /etc/apt/sources.list将以下内容粘贴进去 deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmwaredeb https://mirrors.tuna.tsing…

yolov5中的C3、yolov8中的C2f的【全称】和【代码】

文章目录 yolov5的C3全称yolov8的C2f全称 yolov5的C3全称 点击可找到C3模块然后查看全称:https://github.com/ultralytics/yolov5/blob/master/models/common.py全称为:CSP Bottleneck with 3 convolutions C3模块代码 class C3(nn.Module):# CSP Bott…

AI大模型探索之路-训练篇5:大语言模型预训练数据准备-词元化

系列文章目录🚩 AI大模型探索之路-训练篇1:大语言模型微调基础认知 AI大模型探索之路-训练篇2:大语言模型预训练基础认知 AI大模型探索之路-训练篇3:大语言模型全景解读 AI大模型探索之路-训练篇4:大语言模型训练数据…

DML触发器的创建

目录 触发器的创建 DML触发器的创建 语句级 DML 触发器的创建 创建触发器,当对emp数据表进行添加记录、更新记录和删除记录的时候,判断是否是工作时间段,如果不是工作时间段,不允许执行 在数据表 dept 上创建触发器&#xff…

linux支持vGPU方案

1,查询gpu型号:lspci | grep "NVIDIA\|VGA" PCI Devices 2,下载驱动 官方驱动 | NVIDIA 3,安装 sudo sh NVIDIA-Linux-x86_64-440.118.02.run -no-x-check -no-nouveau-check -no-opengl-files参数说明: …

面试:finalize

一、概述 将资源释放和清理放在finalize方法中非常不好,非常影响性能,严重时甚至会引起OOM(Out Of Memory),从Java9开始就被标注为Deprecated,不建议被使用了。 二、两个重要的队列 1、unfinalized 队列 当…

面向对象开发技术(第三周)

回顾 上一堂课主要学习了面向对象编程与非面向对象编程(面向功能、过程编程),本节课就重点来看看面向对象编程中的一个具体思想——抽象 面向对象编程的特性:1、封装性 2、继承性 3、多态性 封装:意味着提供服务接口…