Redis开发与运维读书笔记-第二章-哈希数据类型介绍(三)

二.哈希数据类型

在Redis中,哈希类型是指键值本身又是一个键值对 结构,形如value={{field1,value1},...{fieldN,valueN}},Redis键值对和 哈希类型二者的关系可以用下图来表示:

 哈希类型中的映射关系叫作field-value,注意这里的value是指field对应的值,不是键对应的值,请注意value在不同上下文的作用。

(一)相关命令

(1)设置值(hset key field value)

下面为user:1添加一对field-value:

127.0.0.1:6379> hset user:1 name tom 
(integer) 1

如果设置成功会返回1,反之会返回0。此外Redis提供了hsetnx命令,它们的关系就像set和setnx命令一样,只不过作用域由键变为field。
(2)获取值(hget key field)
下面操作获取user:1的name域(属性)对应的值:

127.0.0.1:6379> hget user:1 name 
"tom"

如果键或field不存在,会返回nil:

127.0.0.1:6379> hget user:2 name 
(nil) 
127.0.0.1:6379> hget user:1 age 
(nil)

(3)删除field(hdel key field [field ...])
hdel会删除一个或多个field,返回结果为成功删除field的个数,例如:

127.0.0.1:6379> hdel user:1 name 
(integer) 
1 127.0.0.1:6379> hdel user:1 age 
(integer) 0

(4)计算field个数(hlen key)
例如user:1有3个field:

127.0.0.1:6379> hset user:1 name tom 
(integer) 1 
127.0.0.1:6379> hset user:1 age 23 
(integer) 1 
127.0.0.1:6379> hset user:1 city tianjin 
(integer) 1 
127.0.0.1:6379> hlen user:1 
(integer) 3

(5)批量设置或获取field-value(hmget key field [field ...] &&hmset key field value [field value ...])
hmset和hmget分别是批量设置和获取field-value,hmset需要的参数是key 和多对field-value,hmget需要的参数是key和多个field。例如:

127.0.0.1:6379> hmset user:1 name mike age 12 city tianjin 
OK 
127.0.0.1:6379> hmget user:1 name city 
1) "mike" 
2) "tianjin"

(6)判断field是否存在(hexists key field)
例如,user:1包含name域,所以返回结果为1,不包含时返回0:

127.0.0.1:6379> hexists user:1 name 
(integer) 1

(7)获取所有field(hkeys key)
hkeys命令应该叫hfields更为恰当,它返回指定哈希键所有的field,例如:

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

(8) 获取所有value(hvals key)
下面操作获取user:1全部value:

127.0.0.1:6379> hvals user:1 
1) "mike" 
2) "12" 
3) "tianjin"

(9) 获取所有的field-value(hgetall key)
下面操作获取user:1所有的field-value:

127.0.0.1:6379> hgetall user:1 
1) "name" 
2) "mike" 
3) "age" 
4) "12" 
5) "city" 
6) "tianjin"

在使用hgetall时,如果哈希元素个数比较多,会存在阻塞Redis的可能。 如果开发人员只需要获取部分field,可以使用hmget,如果一定要获取全部 field-value,可以使用hscan命令,该命令会渐进式遍历哈希类型
(10)hincrby hincrbyfloat(hincrby key field hincrbyfloat key field)

hincrby和hincrbyfloat,就像incrby和incrbyfloat命令一样,但是它们的作 用域是filed
(11)计算value的字符串长度(需要Redis3.2以上)(hstrlen key field)
例如hget user:1name的value是tom,那么hstrlen的返回结果是3:

127.0.0.1:6379> hstrlen user:1 name 
(integer) 3

(二) 内部编码

哈希类型的内部编码有两种:
·ziplist(压缩列表):当哈希类型元素个数小于hash-max-ziplist-entries 配置(默认512个)、同时所有值都小于hash-max-ziplist-value配置(默认64 字节)时,Redis会使用ziplist作为哈希的内部实现,ziplist使用更加紧凑的 结构实现多个元素的连续存储,所以在节省内存方面比hashtable更加优秀
·hashtable(哈希表):当哈希类型无法满足ziplist的条件时,Redis会使 用hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降,而 hashtable的读写时间复杂度为O(1)。
下面的示例演示了哈希类型的内部编码,以及相应的变化。
1)当field个数比较少且没有大的value时,内部编码为ziplist:

127.0.0.1:6379> hmset hashkey f1 v1 f2 v2 
OK 
127.0.0.1:6379> object encoding hashkey 
"ziplist"

2)当有value大于64字节,内部编码会由ziplist变为hashtable:

127.0.0.1:6379> hset hashkey f3 "one string is bigger than 64 byte...忽略..." 
OK 
127.0.0.1:6379> object encoding hashkey 
"hashtable"

3)当field个数超过512,内部编码也会由ziplist变为hashtable:

127.0.0.1:6379> hmset hashkey f1 v1 f2 v2 f3 v3 ...忽略... f513 v513 
OK 
127.0.0.1:6379> object encoding hashkey 
"hashtable"

(三)使用场景

下图为关系型数据表记录的两条用户信息,用户的属性作为表的列,每条用户信息作为行

 如果将其用哈希类型存储,如下图:

相比于使用字符串序列化缓存用户信息,哈希类型变得更加直观,在更新操作上会更加便捷

需要注意的是哈希类型和关系型数据库有两点不同之处
·哈希类型是稀疏的,而关系型数据库是完全结构化的,例如哈希类型 每个键可以有不同的field,而关系型数据库一旦添加新的列,所有行都要为 其设置值(即使为NULL),如下图所示。
·关系型数据库可以做复杂的关系查询,而Redis去模拟关系型复杂查询开发困难,维护成本高。

目前为止,我们已经能够用三种方法缓存用户信息,下面给出三种方案的实现方法和优缺点分析。
1)原生字符串类型:每个属性一个键。

set user:1:name tom 
set user:1:age 23 
set user:1:city beijing

优点简单直观,每个属性都支持更新操作。
缺点:占用过多的键,内存占用量较大,同时用户信息内聚性比较差,所以此种方案一般不会在生产环境使用

2)序列化字符串类型:将用户信息序列化后用一个键保存。

set user:1 serialize(userInfo)

优点:简化编程,如果合理的使用序列化可以提高内存的使用效率。
缺点:序列化和反序列化有一定的开销,同时每次更新属性都需要把全 部数据取出进行反序列化,更新后再序列化到Redis中。

3)哈希类型:每个用户属性使用一对field-value,但是只用一个键保存。

hmset user:1 name tomage 23 city beijing

优点:简单直观,如果使用合理可以减少内存空间的使用。
缺点:要控制哈希在ziplist和hashtable两种内部编码的转换,hashtable会消耗更多内存。

小结:

设值:hset hashname field value(hset是设值命令,hashname是集合名字,field是字段名,value是值)
取值:hget hashname field 
批量设置:hmset hashname field1 value1 field2 value2 ….
批量取值:hmget hashname field1 field2 ...
hsetnx:和setnx大同小异
hincrby:指定字段增加指定值
hexists:是否存在key,如果存在返回,不存在返回0
删除:hdel 删除指定的hash的field
hlen:返回hash集合里的所有的键数值(size)
hkeys:返回hash里所有的字段
hvals:返回hash的所有value	
hgetall:返回hash里所有的key和value

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值