前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis中的Hash类型

Redis中的Hash类型

作者头像
爱敲代码的猫
发布2020-04-22 11:43:45
1.3K0
发布2020-04-22 11:43:45
举报

Redis-Hash

续上一篇Redis-String,本篇文章为了复习和巩固而记录,这次是到Redis的Hash类型了

  • 结构
  • 内部编码
  • 命令和栗子
  • String与Hash对比

结构

key

fieId

value

user:1:info

name

aquan

age

23

date

905

viewCounter

658

PS:可以看成一个 key 对应这一个对象里面有很多属性,fieId是不可以相同的

内部编码

Hash类型的内部编码有两种,ziplist压缩列表,hashtable哈希表。

  • ziplist:当哈希类型元素个数小于hash-max-ziplist-entries配置(默认512个),同时所有值都小于hash-max-ziplist-value配置(默认64个字节)时,Redis会使用ziplist作为哈希的内部实现ziplist使用更加紧凑的结构实现多个元素的连续存储,所以在节省内存方面比hashtable更加优秀。
  • hashtable:当哈希类型无法满足ziplist的条件时,Redis会使用hashtable作为哈希的内部实现。因为此时ziplist的读写效率会下降,而hashtable的读写时间复杂度为O(1)。

我们利用命令进行一下操作

127.0.0.1:6379> hgetall user:1:info
1) "age"
2) "27"
3) "pageview"
4) "2.5"
5) "name"
6) "aquan"
7) "height"
8) "180"
127.0.0.1:6379> object encoding user:1:info
"ziplist"
127.0.0.1:6379> hset user:1:info signature "寻寻觅觅,冷冷清清,凄凄惨惨戚戚。乍暖还寒时候,最难将息。三杯两盏淡酒,怎敌他、晚来风急!雁过也,正伤心,却是旧时相识。"
127.0.0.1:6379> hgetall user:1:info
 1) "height"
 2) "180"
 3) "age"
 4) "27"
 5) "name"
 6) "aquan"
 7) "pageview"
 8) "2.5"
 9) "signature"
10) "\xd1\xb0\xd1\xb0\xc3\xd9\xc3\xd9\xa3\xac\xc0\xe4\xc0\xe4\xc7\xe5\xc7\xe5\xa
3\xac\xc6\xe0\xc6\xe0\xb2\xd2\xb2\xd2\xc6\xdd\xc6\xdd\xa1\xa3\xd5\xa7\xc5\xaf\xb
b\xb9\xba\xae\xca\xb1\xba\xf2\xa3\xac\xd7\xee\xc4\xd1\xbd\xab\xcf\xa2\xa1\xa3\xc
8\xfd\xb1\xad\xc1\xbd\xd5\xb5\xb5\xad\xbe\xc6\xa3\xac\xd4\xf5\xb5\xd0\xcb\xfb\xa
1\xa2\xcd\xed\xc0\xb4\xb7\xe7\xbc\xb1\xa3\xa1\xd1\xe3\xb9\xfd\xd2\xb2\xa3\xac\xd
5\xfd\xc9\xcb\xd0\xc4\xa3\xac\xc8\xb4\xca\xc7\xbe\xc9\xca\xb1\xcf\xe0\xca\xb6\xa
1\xa3"
127.0.0.1:6379> object encoding user:1:info
"hashtable"

命令和栗子

「hget,hset,hdel」

命令

解释

时间复杂度

hget key fieId

获取hash key对应的fieId的value

O(1)

hset key fieId value

设置hash key对应的fieId的value

O(1)

hdel key field

删除hash key对应的fieId的value

O(1)

127.0.0.1:6379> hset user:1:info name aquan
(integer) 0
127.0.0.1:6379> hget user:1:info name
"aquan"
127.0.0.1:6379> hdel user:1:info name
(integer) 1
127.0.0.1:6379> hget user:1:info name
(nil)

「hexists,hlen」

命令

解释

时间复杂度

hexists key fieId

判断hash key是否存在fieId

O(1)

hlenkey fieId value

获取hash key fieId的数量

O(1)

127.0.0.1:6379> hgetall user:1:info
1) "age"
2) "27"
3) "pageview"
4) "3"
127.0.0.1:6379> hexists user:1:info age
(integer) 1
127.0.0.1:6379> hexists user:1:info name
(integer) 0
127.0.0.1:6379> hlen user:1:info
(integer) 2

「hmget,hmset」

命令

解释

时间复杂度

hmget key fieId1 fieId2 .. fieIdN

批量获取hash key的一批fieId对应的值

O(n)

hmset key fieId1 value1 fieId2 value2 ..

批量设置hash key的一批fieId value

O(n)

127.0.0.1:6379> hgetall user:1:info
1) "age"
2) "27"
3) "pageview"
4) "3"
127.0.0.1:6379> hmget user:1:info age pageview
1) "27"
2) "3"
127.0.0.1:6379> hmset user:1:info name "aquan" height 180
OK
127.0.0.1:6379> hgetall user:1:info
1) "age"
2) "27"
3) "pageview"
4) "3"
5) "name"
6) "aquan"
7) "height"
8) "180"

「hgetall,hvals,hkeys」

命令

解释

时间复杂度

hgetall key

获取hash key中所有的fieId和value

O(n)

hvals key

返回hash key对应所有fieId的value(不返回fieId)

O(n)

hkeys key

返回hash key对应所有的fieId

O(n)

PS:hgetall谨慎使用在线上环境,谨记Redis是单线程,要是线上环境hash key里的fieId属性值多的话,hgetall命令返回时间就会长,后面的命令就会进行排队等待,建议使用hmget命令代替hgetall获取需要的fieId

127.0.0.1:6379> hgetall user:1:info
1) "age"
2) "27"
3) "pageview"
4) "3"
5) "name"
6) "aquan"
7) "height"
8) "180"
127.0.0.1:6379> hvals user:1:info
1) "27"
2) "3"
3) "aquan"
4) "180"
127.0.0.1:6379> hkeys user:1:info
1) "age"
2) "pageview"
3) "name"
4) "height"

「hsetnx,hincrby,hincrbyfloat」

命令

解释

时间复杂度

hsetnx key fieId value

设置hash key对应fieId的value(如fieId已经存在了,则失败)

O(1)

hincrby key fieId num

hash key对应的fieId的value自增num(num可以为正负整数)

O(1)

hincrbyfloat key fieId num

hincrby的浮点数版本

O(1)

PS:fieId不可重复,fieId对应的value可以重复。

127.0.0.1:6379> hgetall user:1:info
1) "age"
2) "27"
3) "pageview"
4) "3"
5) "name"
6) "aquan"
7) "height"
8) "180"
127.0.0.1:6379> hsetnx user:1:info name "haha"
(integer) 0
127.0.0.1:6379> hgetall user:1:info
1) "age"
2) "27"
3) "pageview"
4) "3"
5) "name"
6) "aquan"
7) "height"
8) "180"
127.0.0.1:6379> hincrby user:1:info pageview 2
(integer) 5
127.0.0.1:6379> hincrby user:1:info pageview -1
(integer) 4
127.0.0.1:6379> hincrbyfloat user:1:info pageview -1.5
"2.5"
127.0.0.1:6379> hgetall user:1:info
1) "age"
2) "27"
3) "pageview"
4) "2.5"
5) "name"
6) "aquan"
7) "height"
8) "180"

String与Hash对比

「相似的API」

String

Hash

get

hget

set,setnx

hset,hsetnx

del

hdel

incr,incrby,decr,decrby

hincrby

mset

hmset

mget

hmget

「存储用户信息场景对比」

  • v1:使用String实现

key

value(serializable:Json,xml,protobuf)

user:1

{"id":1,"name":"aquan","age":23,"pageView":905}

存储结构如上表,这样做是一个key对应整个用户信息序列化后的JSONxml等,这样更新数据,存储数据都要进行序列化操作,更新一个小的属性的情况,例如更新age更新到24,那就先要把这个age属性更新到24,整个对象序列化后,再整个更新到整个user:1对应的key中的value中。


  • v2:使用String实现

key

value

user:1:name

aquan

user:1:age

23

user:1:pageView

905

存储结构如上表,可以看到对比v1方法是把信息拆分为3个key单独存储用户对应的信息,这样做的好处可以部分更新,不用整个覆盖更新,直观,添加新的属性也方便,不影响之前的key,这样做后用户的信息不是一个整体,分散到个个key中,不便于管理。


  • v3:使用Hash实现

key

fieId

value

user:1:info

name

aquan

age

23

viewCounter

905

存储结构如上表,这样做可以实现使用fieId进行单独的属性更新,删除与新增,也让用户信息成为整体方便管理

v1,v2,v3优缺点分析

方案

优点

缺点

v1

编程简单,可能节约内存

序列化开销,设置属性要操作整个数据

v2

直观,可以部分更新

内存占用较大,key较分散

v3

直观,节省空间,可以部分更新

编程稍微复杂,ttl过期时间不好可控制

PS:过期时间只能针对key设置,无法针对key中二级属性进行设置,但是可以在逻辑层面进行删除和管理。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-04-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 爱敲代码的猫 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Redis-Hash
    • 结构
      • 内部编码
        • 命令和栗子
          • String与Hash对比
          相关产品与服务
          云数据库 Redis
          腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档