dot 速度的未来即将降临您所在的城市。

加入我们在 Redis 发布会

使用 Redis 进行索引

本文最初发布在 nosqlgeek.org

如果您关注我在 Twitter 上的新闻,您可能已经意识到我开始更多地使用 Redis。Redis (=Remote Dictionary Server) 被称为数据结构存储。这意味着我们不仅可以处理键值对(在 Redis 中称为字符串),还可以处理数据结构,如哈希(哈希映射)、列表、集合或有序集合。有关数据结构的更多详细信息,请参见此处

键值存储中的索引

对于纯粹的键值存储,您通常会通过应用一些 KV 存储模式来手动维护索引结构。以下是一些示例

  • 通过主键直接访问:密钥本身在语义上是有意义的,因此您可以通过了解密钥的结构来直接访问值(通过使用密钥模式)。例如,通过知道用户的 ID 来访问用户配置文件。密钥看起来像“user::<uid>”。
  • 通过辅助键进行精确匹配:KV 存储本身可以看作是一个巨大的哈希映射,这意味着您可以使用查找项来引用其他项。这为您提供了一种哈希索引。例如,通过电子邮件地址查找用户。查找项的键为“email::<email_addr>”,其中值为用户的键。为了获取具有特定电子邮件地址的用户,您只需要对带有电子邮件前缀的键执行 Get 操作,然后对带有用户前缀的键执行另一个 Get 操作。
  • 通过辅助键进行范围查询:对于纯粹的 KV 存储来说,这变得更加复杂。大多数 KV 存储允许您检索所有键的列表,但执行完整的“键空间扫描”效率不高(复杂度为 O(n),n=键数)。您可以通过将列表存储为值并在它们之间进行引用来构建自己的树结构,但维护应用程序端的这些搜索树通常不是您想要做的。

Redis 方法

那么 Redis 如何解决这些示例?我们利用哈希和有序集合等数据结构的力量。

通过主键进行直接访问

Get 操作的复杂度已经是 O(1)。Redis 也是如此。

通过辅助键进行精确匹配

哈希(顾名思义)可以直接用于构建哈希索引,以支持精确匹配“查询”。在 Redis 哈希中访问条目的复杂度实际上是 O(1)。以下是一个示例

HMSET idx_email david.maier@redis.com user::dmaier
HMSET idx_email max.mustermann@example.com user::mustermann
HGET idx_email david.maier@redis.com
"user::dmaier"

此外,Redis 哈希支持 HSCAN 等操作。这为您提供了基于光标的方法来扫描哈希。更多信息请参见此处

以下是一个示例

HSCAN idx_email 0 match d*
1) "0"
2) 1) "david.maier@redis.com"
2) "user::dmaier"

通过辅助键进行范围查询

有序集合可用于支持范围“查询”。我们使用要搜索的值作为分数(排序号)。因此,扫描此类有序集合的复杂度为 O(log(n)+m),其中 n 是集合中的元素数,m 是结果集大小。以下是一个示例

ZADD idx_age 37 user::david
ZADD idx_age 9 user::philip
ZADD idx_age 36 user::katrin
ZADD idx_age 13 user::robin
ZADD idx_age 0 user::samuel
ZRANGEBYSCORE idx_age 0 10
1) "user::samuel"
2) "user::philip"

如果您添加具有相同分数的 2 个元素,则它们将按字典顺序排序。这对非数值很有用。ZRANGEBYLEX 命令允许您通过考虑字典顺序来执行范围“查询”。

模块

Redis 现在支持模块(自 v4.0 起)。模块允许您扩展 Redis 的功能。与本文主题完美匹配的一个模块是 RediSearch。RediSearch 基本上为 Redis 提供了全文索引和搜索功能。它在后台使用倒排索引。有关 RediSearch 的更多详细信息,请参见此处

以下是从 RediSearch 文档中摘取的一个非常基本的示例

FT.CREATE myIdx SCHEMA title TEXT WEIGHT 5.0 body TEXT url TEXT
FT.ADD myIdx doc1 1.0 FIELDS title "hello world" body "lorem ipsum" url "https://redis.ac.cn"
FT.SEARCH myIdx "hello world" LIMIT 0 10
1) (integer) 1
2) "doc1"
3) 1) "title"
2) "hello world"
3) "body"
4) "lorem ipsum"
5) "url"
6) "https://redis.ac.cn"

像往常一样,我希望您发现本文有用且内容丰富。欢迎反馈!