【Redis】Hash 哈希

在这里插入图片描述

Redis 存储键值对,也就是 key - value,不过同时也允许 value 也为键值对,但此时为了避免冲突,为 field - value

PS:hash 哈希的 value 只能为 string 类型

在这里插入图片描述

常用命令

hset

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

hest key field value [field value…]

备注:可同时设置多组,不存在为添加,存在则会覆盖原先的值
返回值:添加的字段的个数,如果是覆盖,则不会计数

示例:

127.0.0.1:6379> hset hash1 f1 111 f2 222 f3 333
(integer) 3
127.0.0.1:6379> hset hash1 f1 1111 f2 2222 f3 3333
(integer) 0

hget

获取 hash 中指定字段(field)的值(value)
语法:

hget key field

备注:hget 不支持同时获取多个
返回值:字段对应的值,不存在则为 nil

示例:

127.0.0.1:6379> hget hash1 f1
"1111"
127.0.0.1:6379> hget hash1 f4
(nil)
127.0.0.1:6379> hget hash10086 f1
(nil)

hmget

获取 hash 中多个字段(field)的值(value)
语法:

hmget key field [field …]

返回值:字段对应的值,若不存在则返回 nil;按获取的顺序返回

示例:

127.0.0.1:6379> hset hash1 f1 111 f2 222 f4 444
(integer) 3
127.0.0.1:6379> hmget hash1 f1 f4 f2
1) "111"
2) "444"
3) "222"
127.0.0.1:6379> hmget hash1 f1 f4 f2 f5
1) "111"
2) "444"
3) "222"
4) (nil)

hexists

判断 hash 中是否有指定的字段(field)
语法:

hexists key field

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

示例:

127.0.0.1:6379> hexists hash1 f1
(integer) 1
127.0.0.1:6379> hexists hash1 f10086
(integer) 0
127.0.0.1:6379> hexists hash2 f1
(integer) 0

hkeys

获取 hash 中所有的字段(field)
语法:

hkeys key

备注:若字段过多,可能会造成 Redis 阻塞,慎用
返回值:字段列表

示例:

127.0.0.1:6379> hkeys hash1
1) "f1"
2) "f2"
3) "f3"

hvals

获取 hash 中所有的值(value)
语法:

hvals key

备注:若字段(field)过多,值(value)也就过多,可能造成 Redis 阻塞,慎用
返回值:所有的值

示例:

127.0.0.1:6379> hvals hash1
1) "1111"
2) "2222"
3) "3333"

hgetall

获取 hash 中所有的字段及其对应的值
语法:

hgetall key

备注:字段(field)和 值(value)不在同一行,但紧挨着
返回值:字段和对应的值

示例:

127.0.0.1:6379> hgetall hash1
1) "f1"
2) "1111"
3) "f2"
4) "2222"
5) "f3"
6) "3333"

hdel

删除 hash 中指定的字段(field)
语法:

hdel key field [field …]

备注:支持删除多个字段
返回值:本次操作删除的字段个数

示例:

127.0.0.1:6379> hdel hash1 f4
(integer) 0
127.0.0.1:6379> hdel hash1 f1 f2
(integer) 2

hlen

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

hlen key

返回值:字段个数

示例:

127.0.0.1:6379> hlen hash1
(integer) 4

hsetnx

在字段不存在的情况下,设置 hash 中的字段(field)和值(value)

语法:

hsetnx key field value

备注:不支持同时设置多个
返回值:1 表示设置成功,0 表示失败

示例:

127.0.0.1:6379> hsetnx hash1 f1 111111
(integer) 0
127.0.0.1:6379> hsetnx hash1 f5 555
(integer) 1

hincrby

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

语法:

hincrby key field increment

备注:正数相加,负数相减,若不为整数,则报错
返回值:该字段(field)变化后的值

示例:

127.0.0.1:6379> hincrby hash1 f1 10
(integer) 121
127.0.0.1:6379> hincrby hash1 f1 -5
(integer) 116
127.0.0.1:6379> hset hash1 str1 hello
(integer) 1
127.0.0.1:6379> hincrby hash1 str1 10
(error) ERR hash value is not an integer

hincrbyfloat

将 hash 中字段对应的数值添加指定的值,浮点数版本

语法:

hincrbyfloat key field increment

备注:正数相加,负数相减,若不为整数/浮点型,则报错
返回值:该字段(field)变化后的值

示例:

127.0.0.1:6379> hincrbyfloat hash1 f2 13.33
"235.33"
127.0.0.1:6379> hincrbyfloat hash1 f2 -5.33
"230"
127.0.0.1:6379> hincrbyfloat hash1 str1 -5.33
(error) ERR hash value is not a float

内部编码

哈希的内部编码有两种

  • ziplist(压缩列表):当哈希类型元素个数小于 hash-max-ziplist-entries(默认为512个),同时所有的值都小于 hash-max-ziplist-value(默认为64字节)时,Redis 会选择使用 ziplist 作为哈希的内部实现。其使用更加紧凑的结构实现多个元素的连续存储,节省内存消耗
  • hashtable (哈希表):当哈希类型无法满足上述条件时,则会使用 hashtable 作为内部实现,因为此时 ziplist 的读写效率下降

上述配置都可以在/etc/redis/redis.conf中进行修改配置,适应不同的业务场景

应用场景

哈希也经常被运用于缓存的场景

现在有如下关系型数据库记录的两条用户信息:

在这里插入图片描述

使用 Redis 有三种缓存方式

  1. 使用 string 一个属性一个键

在这里插入图片描述
虽然也能缓存,但这种方式将一条数据分开缓存,占用过多的键,内存占用量较大,同时用户信息分散,缺少内聚性,基本是不会使用这种方法

  1. 使用 string,使用格式化记录一条数据,例如 json

在这里插入图片描述
优点:如此就可以减小内存占用量,以整体作为操作的信息,编程也相对简单。如果序列化方案选择合适,内存的使用率还将更高
缺点:但如此就会有序列化和反序列化的开销。如果要对其中的一列属性作修改也麻烦:首先要反序列化,修改部分数据,再序列化存储

  1. 哈希类型

在这里插入图片描述

相比于使用格式化字符串,哈希类型变得更加直观,在更新操作上也更灵活
而且哈希类型是稀疏的,因为关系型数据库是完全结构化的,即使该记录没有其中属性,也至少要标识 NULL;而 Redis 就不需要

在这里插入图片描述

PS:但关系型数据库可以做复杂的关系查询,例如联表查询、聚合查询,排序等;这些 Redis 并没有原生支持,如果要实现,需要程序猿手动编码


以上就是本篇博客的所有内容,感谢你的阅读
如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。
在这里插入图片描述

### Redis哈希冲突的解决方案 在 Redis 的设计中,为了应对哈希冲突的情况,默认情况下使用了两个哈希表。其中一个哈希表(哈希表2)在未发生大量哈希冲突时不预先分配内存空间[^2]。 #### 渐进式 rehash 方案 当哈希冲突变得频繁时,Redis 实施了一种称为 **渐进式 rehash** 的策略来处理这个问题。该方法的核心在于逐步迁移键值对到新的哈希表中,而不是一次性完成整个重哈希操作。具体来说,在每次执行命令的过程中,Redis 都会检查当前是否正在进行 rehash;如果是,则会在后台自动将一部分桶的数据迁移到新创建的哈希表上。这种方式可以有效减少因大规模数据移动带来的延迟影响。 #### Rehash 过程中的读写支持 在整个 rehash 期间,旧有的哈希表仍然可用,这意味着客户端依然能够正常地进行查询、插入以及删除等操作而不会受到干扰。对于新增加或者更新的数据项,它们会被放置于最新的哈希表里;而对于来自旧有哈希表上的请求,则通过遍历两个表格来进行定位和响应[^3]。 ```python def get_value(key, hash_table_1, hash_table_2=None): value = hash_table_1.get(key) if not value and hash_table_2 is not None: value = hash_table_2.get(key) return value def set_value(key, value, hash_table_1, hash_table_2=None): if hash_table_2 is not None: hash_table_2[key] = value else: hash_table_1[key] = value ``` 这种机制不仅提高了系统的稳定性和效率,同时也简化了应用程序层面的设计复杂度,因为开发者无需特别考虑底层存储结构的变化所带来的兼容性问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值