1

这是一个后续问题Segmenting Redis By Database。我最初询问了一个redis实例中不同数据库中redis键操作的时间复杂度。我问的原因是因为我正在尝试实现一个缓存,其中有x 个多段键,每个键可能有y个实际数据实例,导致xy个总键。

但是,我想支持主键的通配符搜索,似乎在 redis 中唯一实现的键通配符查询是keys命令,不鼓励使用。在我看来,将x键放在单独的数据库中似乎是一个不错的折衷方案,其中较少数量的键将使操作令人满意地执行。

任何人都可以提出更好的选择吗?

谢谢。

4

1 回答 1

4

我仍然认为使用 KEYS 确实无法通过 Redis 进行扩展,无论您可以采用何种巧妙的方案来解决线性复杂性问题。

分区就是其中一种方案,在传统的RDBMS中常用来降低对平面表的表扫描成本。你的想法其实是这个概念对 Redis 的改编。

但与提供此功能的传统 RDBMS(Oracle、MySQL...)相比,有一个重要的区别:Redis 是一个单线程事件循环。因此,扫描不能与任何其他活动同时进行(例如服务其他客户端连接)。Redis 扫描数据时,所有连接都会被阻塞。

您必须设置大量分区(即数据库)才能获得良好的性能。类似于全局键数的 1/1000 或 1/10000。这就是它不可扩展的原因:Redis 并不是为处理如此多的数据库而设计的。您可能会遇到在所有数据库上迭代的内部机制的问题。这是从源代码中提取的列表:

  • 自动重新散列
  • 物品过期管理
  • 数据库状态记录(每 5 秒)
  • 信息命令
  • 最大内存管理

您可能必须限制数据库的数量,这也限制了可伸缩性。如果您设置 1000 个数据库,那么对于 100 万个项目将可以正常工作,对于 100 万个项目会更慢,而对于 100 万个项目则无法使用。

如果您仍想坚持使用线性扫描来实现此功能,那么其​​他支持并发扫描的商店(如 MySQL、MongoDB 等)将为您提供更好的服务。对于其他商店,关键是要以有效的方式实施商品过期。

如果你真的要使用 Redis,你可以很容易地对数据进行分段,而不需要依赖多个数据库。例如,您可以使用我在此处描述的方法。使用这种策略,键列表以增量方式检索,搜索实际上是在客户端完成的。主要的好处是你可以拥有大量的分区,这样 Redis 就不会阻塞。

现在,AFAIK 没有存储引擎提供使用任意正则表达式有效搜索数据的能力(即避免线性扫描)。但是,此功能由某些搜索引擎提供,通常使用 n-gram 索引。

这是来自 Russ Cox 的一篇很好的文章:http: //swtch.com/~rsc/regexp/regexp4.html

这种索引机制可能适用于 Redis(您将使用 Redis 存储键的三元组索引),但它需要编写大量代码。

您还可以想象将正则表达式限制为前缀搜索。例如 U:SMITH:(.*) 实际上是一个带有前缀 U:SMITH 的搜索:

在这种情况下,您可以使用 zset 索引您的键,并在检索到您感兴趣的键范围后在客户端执行线性搜索。zset 中项目的分数是根据客户端的键计算的,因此分数顺序与键的字典顺序相对应。

使用这样的 zset,可以通过 zscore 和 zrange 命令的组合检索必须逐块扫描的键范围。其后果是扫描的键数量受到限制(受前缀),搜索发生在客户端,并且对 Redis 并发模型很友好。缺点是复杂性(尤其是处理项目过期)和网络带宽消耗。

于 2012-05-27T07:58:38.303 回答