Redis 哈希对象
2023-3-24
| 2023-8-2
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password
Property

Redis hash(哈希散列)是由字符类型的 field(字段)和 value 组成的哈希映射表结构(也称散列表),它非常类似于表格结构。在 hash 类型中,field 与 value 一一对应,且不允许重复。
Redis hash特别适合于存储对象。一个filed/value可以看做是表格中一条数据记录;而一个key可以对应多条数据。例如,使用 hash 类型存储表格中的数据,这里以user
keyid:1为字段,name:Caovalue
通过上述方法,就把表格中的数据存储在了内存中。Redis hash 的存储结构如下图所示:
notion image
一个 hash 类型的 key 最多可以存储 (约 40 亿个)字段/值。同时 Redis hash 会为这个 key 额外储存一些附加的管理信息,比如这个键的类型、最后一次访问这个键的时间等,所以 hash 键越来越多时,Redis 耗费在管理信息方面的内存就越多。当 hash 类型移除最后一个元素后,该存储结构就会被自动删除,其占用内存也会被系统回收。
 
 
哈希对象的编码可以是 ziplist 或者 hashtable 。
ziplist 编码的哈希对象使用压缩列表作为底层实现, 每当有新的键值对要加入到哈希对象时, 程序会先将保存了键的压缩列表节点推入到压缩列表表尾, 然后再将保存了值的压缩列表节点推入到压缩列表表尾, 因此:
  • 保存了同一键值对的两个节点总是紧挨在一起, 保存键的节点在前, 保存值的节点在后;
  • 先添加到哈希对象中的键值对会被放在压缩列表的表头方向, 而后来添加到哈希对象中的键值对会被放在压缩列表的表尾方向。
举个例子, 如果执行以下 HSET 命令, 那么服务器将创建一个列表对象作为 profile 键的值:
如果 profile 键的值对象使用的是 ziplist 编码:
notion image
 
notion image
 
另一方面, hashtable 编码的哈希对象使用字典作为底层实现, 哈希对象中的每个键值对都使用一个字典键值对来保存:
  • 字典的每个键都是一个字符串对象, 对象中保存了键值对的键;
  • 字典的每个值都是一个字符串对象, 对象中保存了键值对的值。
如果前面 profile 键创建的不是 ziplist 编码的哈希对象, 而是 hashtable编码的哈希对象, 那么这个哈希对象:
notion image
 
 

编码转换

当哈希对象可以同时满足以下两个条件时, 哈希对象使用 ziplist 编码:
  1. 哈希对象保存的所有键值对的键和值的字符串长度都小于 64 字节;
  1. 哈希对象保存的键值对数量小于 512 个;
不能满足这两个条件的哈希对象需要使用 hashtable 编码。在 Redis 7.0 中,压缩列表数据结构已经废弃了,交由 listpack 数据结构来实现了
 
这两个条件的上限值是可以修改的, 具体请看配置文件中关于 hash-max-ziplist-value 选项和 hash-max-ziplist-entries 选项的说明。
对于使用 ziplist 编码的列表对象来说, 当使用 ziplist 编码所需的两个条件的任意一个不能被满足时, 对象的编码转换操作就会被执行: 原本保存在压缩列表里的所有键值对都会被转移并保存到字典里面, 对象的编码也会从 ziplist 变为 hashtable 。
 
 

Redis哈希命令

notion image
  • HDEL:删除一个或多个哈希表字段
  • HEXISTS:查看哈希表 key 中,指定的字段是否存在
  • HGET:获取存储在哈希表中指定字段的值
  • HGETALL:获取在哈希表中指定 key 的所有字段和值
  • HINCRBY:为哈希表 key 中的指定字段的整数值加上增量 increment
  • HINCRBYFLOAT:为哈希表 key 中的指定字段的浮点数值加上增量 increment
  • HKEYS:获取所有哈希表中的字段
  • HLEN:获取哈希表中字段的数量
  • HMGET:获取所有给定字段的值
  • HMSET:同时将多个 field-value (域-值)对设置到哈希表 key 中
  • HSET:将哈希表 key 中的字段 field 的值设为 value
  • HSETNX:只有在字段 field 不存在时,设置哈希表字段的值
  • HVALS:获取哈希表中所有值
  • HSCAN:迭代哈希表中的键值对
  • HSTRLEN:返回哈希表 key 中,与给定域field 相关联的值的字符串长度
 
 

应用场景

缓存对象

Hash 类型的 (key,field, value) 的结构与对象的(对象id, 属性, 值)的结构相似,也可以用来存储对象。
以用户信息为例,它在关系型数据库中的结构是这样的:
notion image
可以使用如下命令,将用户对象的信息存储到 Hash 类型:
Redis Hash 存储其结构如下图:
notion image
在介绍 String 类型的应用场景时有所介绍,String + Json也是存储对象的一种方式,那么存储对象时,到底用 String + json 还是用 Hash 呢?
一般对象用 String + Json 存储,对象中某些频繁变化的属性可以考虑抽出来用 Hash 类型存储。
 

购物车

以用户 id 为 key,商品 id 为 field,商品数量为 value,恰好构成了购物车的3个要素,如下图所示。
notion image
涉及的命令如下:
  • 添加商品:HSET cart:{用户id} {商品id} 1
  • 添加数量:HINCRBY cart:{用户id} {商品id} 1
  • 商品总数:HLEN cart:{用户id}
  • 删除商品:HDEL cart:{用户id} {商品id}
  • 获取购物车所有商品:HGETALL cart:{用户id}
当前仅仅是将商品ID存储到了Redis 中,在回显商品具体信息的时候,还需要拿着商品 id 查询一次数据库,获取完整的商品的信息。
 
  • Redis
  • Redis 列表对象Redis 集合对象
    目录