【redis】数据类型之hash

Redis中的Hash数据类型是一种用于存储键值对集合的数据结构。与Redis的String类型不同,Hash类型允许你将多个字段(field)和值(value)存储在一个单独的key下,从而避免了将多个相关数据存储为多个独立的key。这样做的好处是减少了key的数量,使得数据的管理和操作更加高效。

hash这个数据类型类似java中的HashMap,都由key-value键值对组成。

有关hash类型的命令可以通过help @hash命令来查看。有关命令的使用可以通过help 命令来查看,例如help hset

HSET

hset:设置hash指定字段的值。

语法:

shell 复制代码
HSET key field value [field value ...]

使用:

shell 复制代码
127.0.0.1:6379> hset h1 name morris age 18
(integer) 2

HGET

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

语法:

shell 复制代码
HGET key field

使用:

shell 复制代码
127.0.0.1:6379> hget h1 name
"morris"

HKEYS

hkeys:获取hash所有的字段。

语法:

shell 复制代码
HKEYS key

使用:

shell 复制代码
127.0.0.1:6379> hkeys h1
1) "name"
2) "age"

HVALS

hvals:获取hash所有的值。

语法:

shell 复制代码
HVALS key

使用:

shell 复制代码
127.0.0.1:6379> hvals h1
1) "morris"
2) "18"

HGETALL

hgetall:获取hash所有的字段和值。

语法:

shell 复制代码
HGETALL key

使用:

shell 复制代码
127.0.0.1:6379> hgetall h1
1) "name"
2) "morris"
3) "age"
4) "18"

HEXISTS

hexists:判断hash中某个字段是否存在。

语法:

shell 复制代码
HEXISTS key field

使用:

shell 复制代码
127.0.0.1:6379> hexists h1 name
(integer) 1

HLEN

hlen:返回hash中键值对的个数。

语法:

shell 复制代码
HLEN key

使用:

shell 复制代码
127.0.0.1:6379> hlen h1
(integer) 2

HINCRBY

hincrby:给hash中指定字段的值增加一个整型。

语法:

shell 复制代码
INCRBY key increment

使用:

shell 复制代码
127.0.0.1:6379> hincrby h1 age 1
(integer) 19

HINCRBYFLOAT

hincrbyfloat:给hash中指定字段的值增加一个浮点型。

语法:

shell 复制代码
INCRBYFLOAT key increment

使用:

shell 复制代码
127.0.0.1:6379> hincrbyfloat h1 age 0.5
"19.5"

HSTRLEN

hstrlen:获取hash指定字段的值的长度。

语法:

shell 复制代码
HSTRLEN key field

使用:

shell 复制代码
127.0.0.1:6379> hstrlen h1 name
(integer) 6

HMSET

hmset:批量设置hash,这个跟hset命令一样了,只是hset只支持设置一个,能保证原子性。

语法:

shell 复制代码
HMSET key field value [field value ...]

使用:

shell 复制代码
127.0.0.1:6379> hmset k k1 v1 k2 v2 k3 v3
OK

127.0.0.1:6379> hgetall k
1) "k1"
2) "v1"
3) "k2"
4) "v2"
5) "k3"
6) "v3"

HMGET

hmget:批量获取hash的字段对应的值。

语法:

shell 复制代码
HMGET key field [field ...]

使用:

shell 复制代码
127.0.0.1:6379> hmget k k1 k2 k3
1) "v1"
2) "v2"
3) "v3"

HSETNX

hsetnx:字段不存在则设置成功,类似setnx命令,只能设置一个字段。

语法:

shell 复制代码
HSETNX key field value

使用:

shell 复制代码
127.0.0.1:6379> hsetnx kk name bob
(integer) 1

HDEL

hdel:删除字段。

语法:

shell 复制代码
HDEL key field [field ...]

使用:

shell 复制代码
127.0.0.1:6379> hdel k k1
(integer) 1

127.0.0.1:6379> hkeys k
1) "k2"
2) "k3"

HRANDFIELD

hrandfield:用于随机返回一个或多个存储在指定key中的哈希表(hash)里字段的值。

语法:

shell 复制代码
HRANDFIELD key [count [WITHVALUES]]

使用:

shell 复制代码
127.0.0.1:6379> hrandfield h1 1 withvalues
1) "age"
2) "18"

HSCAN

hscan:用于迭代哈希表(Hashes)中键值对的命令,有点类似于SCAN。

语法:

shell 复制代码
HSCAN key cursor [MATCH pattern] [COUNT count]

使用:

shell 复制代码
127.0.0.1:6379> hscan h1 0 MATCH a* COUNT 1
1) "0"
2) 1) "age"
   2) "18"

内部编码

哈希类型的内部编码有两种:

  • ziplist(压缩列表):当哈希类型元素个数小于hash-max-ziplist-entries配置(默认512个)、同时所有值都小于hash-max-ziplist-value配置(默认64字节)时,Redis会使用ziplist作为哈希的内部实现,ziplist使用更加紧凑的结构实现多个元素的连续存储,所以在节省内存方面比hashtable更加优秀。

  • hashtable(哈希表):当哈希类型无法满足ziplist的条件时,Redis会使用hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降,而hashtable的读写时间复杂度为O(1)。

shell 复制代码
127.0.0.1:6379> object encoding h1
"ziplist"

127.0.0.1:6379> hset y str "one string is bigger than 64 byte...............one string is bigger than 64 byte..............."
(integer) 1

127.0.0.1:6379> object encoding y
"hashtable"

使用场景

hash常用来存储关系型数据库中的记录。

假设现在数据库有一张user表,如下:

下面给出三种方案来缓存用户信息。

  1. 使用原生字符串类型存储,每个属性一个键。
shell 复制代码
127.0.0.1:6379> mset user:1:name morris user:1:age 18 user:1:city beijing
OK

127.0.0.1:6379> mset user:2:name bob user:1:age 20 user:1:city hongkong
OK

127.0.0.1:6379> keys user:1:*
1) "user:1:age"
2) "user:1:name"
3) "user:1:city"

127.0.0.1:6379> mget user:1:name user:1:age user:1:city
1) "morris"
2) "20"
3) "hongkong"

优点:简单直观,每个属性都支持更新操作。

缺点:占用过多的键,内存占用量较大,同时用户信息内聚性比较差。

  1. 将数据库中的一行记录序列化为json,用一个key保存。
shell 复制代码
127.0.0.1:6379> set user:1 '{"id":1,"name":"morris","age":18,"city":"beijing"}'
OK

127.0.0.1:6379> get user:1
"{"id":1,"name":"morris","age":18,"city":"beijing"}"

127.0.0.1:6379> set user:2 '{"id":2,"name":"bob","age":20,"city":"hongkong"}'
OK

127.0.0.1:6379> get user:2
"{"id":2,"name":"bob","age":20,"city":"hongkong"}"

优点:简化编程,如果合理的使用序列化可以提高内存的使用效率。

缺点:序列化和反序列化有一定的开销,同时每次更新属性都需要把全部数据取出进行反序列化,更新后再序列化到Redis中。

  1. 使用hash存储,每行记录的一列对应一个field-value。
shell 复制代码
127.0.0.1:6379> hset user:1 name morris age 18 city beijing
(integer) 3

127.0.0.1:6379> hset user:2 name bob age 20 city hongkong
(integer) 3

127.0.0.1:6379> hgetall user:1
1) "name"
2) "morris"
3) "age"
4) "18"
5) "city"
6) "beijing"

127.0.0.1:6379> hgetall user:2
1) "name"
2) "bob"
3) "age"
4) "20"
5) "city"
6) "hongkong"

优点:简单直观,如果使用合理可以减少内存空间的使用。

缺点:要控制哈希在ziplist和hashtable两种内部编码的转换,hashtable会消耗更多内存。

相关推荐
小陈工3 分钟前
Python Web开发入门(十七):Vue.js与Python后端集成——让前后端真正“握手言和“
开发语言·前端·javascript·数据库·vue.js·人工智能·python
科技小花4 小时前
数据治理平台架构演进观察:AI原生设计如何重构企业数据管理范式
数据库·重构·架构·数据治理·ai-native·ai原生
一江寒逸5 小时前
零基础从入门到精通MySQL(中篇):进阶篇——吃透多表查询、事务核心与高级特性,搞定复杂业务SQL
数据库·sql·mysql
D4c-lovetrain5 小时前
linux个人心得22 (mysql)
数据库·mysql
阿里小阿希5 小时前
CentOS7 PostgreSQL 9.2 升级到 15 完整教程
数据库·postgresql
荒川之神5 小时前
Oracle 数据仓库雪花模型设计(完整实战方案)
数据库·数据仓库·oracle
做个文艺程序员5 小时前
MySQL安全加固十大硬核操作
数据库·mysql·安全
不吃香菜学java6 小时前
Redis简单应用
数据库·spring boot·tomcat·maven
一个天蝎座 白勺 程序猿6 小时前
Apache IoTDB(15):IoTDB查询写回(INTO子句)深度解析——从语法到实战的ETL全链路指南
数据库·apache·etl·iotdb
不知名的老吴6 小时前
Redis的延迟瓶颈:TCP栈开销无法避免
数据库·redis·缓存