Redis数据结构——hash

原创
2019/08/30 15:44
阅读数 11

概述

在Redis中,哈希类型(hash)是指健值本身又是一个健值对结构


value ={{field1,value1},...{fieldN,valueN}}


哈希类型中的映射关系叫做filed-value.这里的value是指filed对应的值,不是健对应的值。Redis键值对和哈希类型二者之间的关系如下

image.png

可以假设成hash 存在两的key ,将字符串key 公共相同部分抽离出来组成第一层key,剩余部分组成第二级key

字符串设置值和获取值


127.0.0.1:6379> set user:1:name tony
OK
127.0.0.1:6379> set user:1:age 20
OK
127.0.0.1:6379> get user:1:name
"tony"
127.0.0.1:6379> get user:1:age
"20"

hash 设置值和获取值


127.0.0.1:6379> hset user:1 name tony
(integer) 1
127.0.0.1:6379> hset user:1 age 20
(integer) 1
127.0.0.1:6379> hget user:1 name
"tony"
127.0.0.1:6379> hget user:1 age
"20"


命令

hest

设置值

hest key field value

设置hash key对应的filed的value,如果设置成功会返回1,反之会返回0。


127.0.0.1:6379> hset user:1 name xiaoming
(integer) 1
127.0.0.1:6379> hset user:1 age 18
(integer) 1


hget

获取值


获取hash key对应的filed的value,如果健或field不存在,会返回nil.



hkeys

hkeys key 获取哈希健所有的field,



hvals

hvals key 获取key 所有的value



hgetall

hgetall key获取所有的filed-value,如果使用hgetall 哈希元素过多的话,会存在阻塞Redis的可能,生产环境禁用。可以使用hscan代替



hincrby

hincrby key field increment整数值累加计算


hdel

hdel key field [field] 会删除一个或多个field,返回结果为成功删除filed的个数。


能使用类似于 hdel hash名称 的命令删除整个 Hash 值的



hexists

hexist key filed 判断hash key 是否存在



hlen

hlen key 获取hash key filed 的数量



hmset

设置hash key 的一批filed对应的值



hmget

获取hash key 的一批filed对应的值



hsetnx

hsetnx key filed value设置hash key 对应的filed的value(如果已经filed则失败),如果尝试插入已存在的键,不会改变原来的值,


源码分析

内部编码

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

ziplist 压缩列表:当哈希类型元素个数小于hash-max-ziplist-entries配置(默认512个),同时所有值都小于hash-max-ziplist-value配置(默认64个字节)redis会使用ziplist作为哈希的内部实现。

hashtable 哈希表 当哈希类型无法满足ziplist的条件是,redis会使用hashtable作为哈希的内部实现。

字典类型本质上是由数组和链表结构组成的

image.png

数组

链表

val

*next

Key

*next

*next

val

key

key

val

渐进式rehash

Redis 为了保证应用的高性能运行,提供了一个重要的机制——渐进式 rehash。 渐进式 rehash 是用来保证字典缩放效率的,也就是说在字典进行扩容或者缩容是会采取渐进式 rehash 的机制。

在进行渐进式 rehash 时,会同时保留两个 hash 结构,新键值对加入时会直接插入到新的 hash 结构中,并会把旧 hash 结构中的元素一点一点的移动到新的 hash 结构中,当移除完最后一个元素时,清空旧 hash 结构,主要的执行流程如下:

  • 扩容或者缩容时把字典中的字段 rehashidx 标识为 0;
  • 在执行定时任务或者执行客户端的 hset、hdel 等操作指令时,判断是否需要触发 rehash 操作(通过 rehashidx 标识判断),如果需要触发 rehash 操作,也就是调用 dictRehash 函数,dictRehash 函数会把 ht[0] 中的元素依次添加到新的 Hash 表 ht[1] 中;
  • rehash 操作完成之后,清空 Hash 表 ht[0],然后对调 ht[1] 和 ht[0] 的值,把新的数据表 ht[1] 更改为 ht[0],然后把字典中的 rehashidx 标识为 -1,表示不需要执行 rehash 操作

应用

存储对象数据

1原生字符串类型,每个属性一个key,占用的key多,内存占用大,用户内聚性比较差

2序列化字符串,将对象信息进行序列化,序列化与反序列化有一定的开销


本文同步分享在 博客“羊羽”(other)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
打赏
0
0 收藏
分享

作者的其它热门文章

加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部