redis 散列

Jackey Redis 3,170 次浏览 , , 没有评论

散列(hash)

一个散列由多个域值对(field-value pair)组成,散列的域和值都可以是文字、整数、浮点数或者二 进制数据。

同一个散列里面的每个域必 须是独一无二、各不相同的,而域的值则没有这一要求,换句话说,不同域的值可以是重复的。

通过命令,用户可以对散列执行设置域值对、获取域的值、检查域是否存在等操作,也可以 让 Redis 返回散列包含的所有域、所有 值或者所有域值对。

关联域值对

HSET key field value
在散列键 key 中关联给定的域值对 field 和 value 。
如果域 field 之前没有关联值,那么命令返回 1 ;
如果域 field 已经有关联值,那么命令用新值覆盖旧值,并返回 0 。
复杂度为 O(1) 。
redis> HSET message "id" 10086
(integer) 1
redis> HSET message "sender" "peter"
(integer) 1
redis> HSET message "receiver" "jack"
(integer) 1

获取域关联的值

HGET key field
返回散列键 key 中,域 field 所关联的值。如果域 field 没有关联值,那么返回 nil 。
复杂度为 O(1) 。
redis> HGET message "id"
"10086"
redis> HGET message "sender"
"peter"
redis> HGET message "content"
"Good morning, jack!"
redis> HGET message "NotExistsField"
(nil)

仅当域不存在时,关联域值对

HSETNX key field value
如果散列键 key 中,域 field 不存在(也即是,还没有与之相关联的值),那么关联给定的域值对 field 和value 。
如果域 field 已经有与之相关联的值,那么命令不做动作。
复杂度为 O(1) 。
redis> HSETNX message "content" "Good morning, jack!"
(integer) 1
redis> HSETNX message "content" "Good morning, jack!"
(integer) 0

检查域是否存在

HEXISTS key field
查看散列键 key 中,给定域 field 是否存在:存在返回 1 ,不存在返回 0 。
复杂度为 O(1) 。
redis> HEXISTS message "id"
(integer) 1
redis> HEXISTS message "sender"
(integer) 1
redis> HEXISTS message "content"
(integer) 0
redis> HEXISTS message "NotExistsField"
(integer) 0

删除给定的域值对

HDEL key field [field ...]
删除散列键 key 中的一个或多个指定域,以及那些域的 值。不存在的域将被忽略。命令返回被成功 删除的域值对数量。
复杂度为 O(N) ,N 为被删除的域值对数量。
redis> HDEL message "id"
(integer) 1
redis> HDEL message "receiver"
(integer) 1
redis> HDEL message "sender"
(integer) 1

获取散列包含的键值对数量

HLEN key
返回散列键 key 包含的域值对数量。
复杂度为 O(1) 。
redis> HLEN message
(integer) 4
redis> HDEL message "date"
(integer) 1
redis> HLEN message
(integer) 3

一次设置或获取散列中的多个域值对

HMSET key field value [field value ...] 在散列键 key 中关联多个域值对,相当于同时执行多个 HSET 。

HMGET key field [field ...] 返回散列键 key 中,一个或多个域的值,相当于同时执行多个 HGET 。

redis> HMSET message "id" 10086 "sender" "peter" "receiver" "jack"
OK
redis> HMGET message "id" "sender" "receiver"
1) "10086"
2) "peter"
3) "jack"

获取散列包含的所有域、值、或者域值对

HKEYS key 返回散列键 key 包含的所有域。 O(N),N 为被返回域的数量。
HVALS key 返回散列键 key 中,所有域的值。 O(N),N 为被返回值的数量。
HGETALL key 返回散列键 key 包含的所有域值对。 O(N),N 为被返回域值对的数量。

为什么命令叫 HKEYS 而不是 HFIELDS ?
对于散列来说,key 和 field 表示的是同一个意思,并且 key 比 field 更容易拼写,
所以 Redis 选择使用 HKEYS 来做命令的名字,而不是 HFIELDS 。

redis> HKEYS message
1) "id"
2) "sender"
3) "receiver"
4) "date"
5) "content"
redis> HVALS message
1) "10086"
2) "peter"
3) "jack"
4) "2014-8-3 3:25 p.m."
5) "Good morning, jack!"

redis> HGETALL message
1) "id" # 域
2) "10086" # 值
3) "sender" # 域
4) "peter" # 值
5) "receiver"
6) "jack"
7) "date"
8) "2014-8-3 3:25 p.m."
9) "content"
10) "Good morning, jack!"

对域的值执行自增操作

HINCRBY key field increment 为散列键 key 中,域 field 的值加上整数增量 increment 。

HINCRBYFLOAT key field increment 为散列键 key 中,域 field 的值加上浮点数增量 increment 。

虽然 Redis 没有提供与以上两个命令相匹配的HDECRBY 命令和 HDECRBYFLOAT 命令,但我们同样可以通过将 increment 设为负数来达到做减法的效果。
redis> HINCRBY numbers x 100 # 域不存在,先将值初始化为 0 ,然后再执行 HINCRBY 操作
(integer) 100
redis> HINCRBY numbers x -50 # 传入负值,做减法
(integer) 50
redis> HINCRBYFLOAT numbers x 3.14 # 浮点数计算
"53.14"

使用散列的好处

  1. 将数据放到同一个地方
    散列可以让我们将一些相关的信息储存在同一个地方,而不是直接分散地 储存在整个数据库里面,这不仅方便了数据管理,还可以尽量避免误操作发生。
  2. 避免键名冲突
    在使用字符串键的时候,可以在命名键的时候,使用分割符来避免命名冲突 ,但更好的办法是直接使用散列键来储存键值对数据。
  3. 减少内存占用
    在一般情况下,保存相同数量的 键值对信息,使用散列键比使用字符串键更节约内存。因为在数据库里面创建的每个键都带有数据库附加的管理信息(比如 这个键的类型、最后一次被访问的时间等等),所以数据库里面的键越多,服务器在储存附加管理信息方面耗 费的内存就越多,花在管理数据库键上的 CPU 也会越多。
    除此之外,当散列包含的域 值对数量比较少的时候,Redis 会自动使用一种占用内存非常少的数据结构来做散列的底层实现,在散列的数量比较多的时候,这一措施对减少内存有很大的帮助。

结论

只要有可能的话,就尽量使用散列键而不是字符串键来储存键值对数据,因为散列键管理方便、能够避免键名冲突、并且还能够节约内存。

使用过期功能:Redis 的键过期功能目前只能对键进行过期操作,而不能对散列的域进行过期操作,因此如果你要对键值对数据使用过期功能的话,那么只能把键值对储存在字符串里面。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

Go