对比 Redis 的字符串和散列

Note

本文摘录自即将出版的《Redis使用手册》, 详情请见: RedisGuide.com

本章从开头到现在, 陆续介绍了 HSET 、 HSETNX 、 HGET 、 HINCRBY 和 HINCRBYFLOAT 等多个散列命令, 如果读者对上一章介绍过的字符串命令还有印象的话, 那么应该会记得, 字符串也有类似的 SET 、 SETNX 、 GET 、 INCRBY 和 INCRBYFLOAT 命令。 这种相似并不是巧合, 正如表 3-1 所示, 散列的确拥有很多与字符串命令功能相似的命令。


表 3-1 字符串命令与类似的散列命令

字符串

散列

SET —— 为一个字符串键设置值。

HSET —— 为散列的给定字段设置值。

SETNX —— 仅在字符串键不存在的情况下为它设置值。

HSETNX —— 仅在散列不包含指定字段的情况下,为它设置值。

GET —— 获取字符串键的值。

HGET —— 从散列里面获取给定字段的值。

STRLEN —— 获取字符串值的字节长度。

HSTRLEN —— 获取给定字段值的字节长度。

INCRBY —— 对字符串键储存的数字值执行整数加法操作。

HINCRBY —— 对字段储存的数字值执行整数加法操作。

INCRBYFLOAT —— 对字符串键储存的数字值执行浮点数加法操作。

HINCRBYFLOAT —— 对字段储存的数字值执行浮点数加法操作。

MSET —— 一次为多个字符串键设置值。

HMSET —— 一次为散列的多个字段设置值。

MGET —— 一次获取多个字符串键的值。

HMGET —— 一次获取散列中多个字段的值。

EXISTS —— 检查给定的键是否存在于数据库当中, 这个命令可以用于包括字符串键在内的所有数据库键, 本书稍后将在《数据库》一章对这个命令进行详细的介绍。

HEXISTS —— 检查给定字段是否存在于散列当中。

DEL —— 从数据库里面删除指定的键, 这个命令可以用于包括字符串键在内的所有数据库键, 本书稍后将在《数据库》一章对这个命令进行详细的介绍。

HDEL —— 从散列中删除给定字段,以及它的值。


对于表中列出的字符串命令和散列命令来说, 它们之间的最大区别就是前者处理的是字符串键, 而后者处理的则是散列键, 除此之外, 这些命令要做的事情几乎都是相同的。

Redis 之所以会选择同时提供字符串键和散列键这两种数据结构, 原因在于它们虽然在操作上非常相似, 但是各自却又拥有不同的优点, 这使得它们在某些场合无法被对方替代。

表 3-2 从资源占用、支持的操作以及过期时间三个方面对比了字符串键和散列键的优缺点。


表 3-2 对比字符串键和散列键

比较的范畴

结果

资源占用

字符串键在数量较多的情况下,将占用大量的内存和 CPU 时间。 与此相反,将多个数据项储存到同一个散列里面可以有效地减少内存和 CPU 消耗。

支持的操作

散列键支持的所有命令,几乎都有相应的字符串键版本,但字符串键支持的 SETRANGEGETRANGE 等操作散列键并不具备。

过期时间

字符串键可以为每个键单独设置过期时间,独立删除某个数据项;而散列一旦到期,它包含的所有字段和值都会被删除。


既然字符串键和散列键各有优点, 那么我们在构建应用程序的时候, 什么时候应该使用字符串键, 而什么时候又应该使用散列键呢? 对于这个问题, 以下总结了一些选择的条件和方法:

  1. 如果程序需要为每个数据项单独设置过期时间, 那么使用字符串键。

  2. 如果程序需要对数据项执行诸如 SETRANGEGETRANGE 或者 APPEND 等操作, 那么优先考虑使用字符串键。 当然, 用户也可以选择把数据储存在散列里面, 然后将类似 SETRANGEGETRANGE 这样的操作交给客户端执行。

  3. 如果程序需要储存的数据项比较多, 并且你希望尽可能地减少储存数据所需的内存, 那么就应该优先考虑使用散列键。

  4. 如果多个数据项在逻辑上属于同一组或者同一类, 那么应该优先考虑使用散列键。