堆栈交换.Redis 密钥空间通知 - 否.订阅者与争用



我正在尝试使用 Redis 实现标记。这是它的样子:

mykey (my item)
mykey:tags (a set with the tags associated to that item)
tags:tag1 (a set with references to all items tagged with "tag1")
...

我计划使用 Redis 密钥空间通知来防止过期密钥永远保留在我的标签集上(即使缓存中的每个项目都有默认的 TTL 集,我也不喜欢保留过时的数据)。

这些是我正在考虑的选项:

1) 订阅所有"过期"事件。

psubscribe '__keyevent@*:expired'

优点:

  • 只有 1 个订阅者。

缺点:

  • 由于并非所有项目都包含标签,我将不得不检查 mykey:tags如果存在,则获取标签并从每个标签集中删除该项目。
  • 此方法的争用将随着密钥数量的增加而增加在商店里。

2) 订阅仅包含标签的密钥的所有事件。

psubscribe '__keyspace@*:mykey'

优点:

  • 将为仅具有标记的项目创建订阅。

缺点:

  • 必须有与每个订阅者关联的开销。
  • 订阅者的数量可以快速增长,具体取决于数量商店中标记的商品。

问题:

  1. 我应该实施哪个选项?我应该担心2)上的订户数量,还是1)上的争用更大交易?我找不到有关此主题的任何建议。
  2. 最终的游戏是在 Redis 集群上实现这一点。这是否增加了对实施有什么额外的关注吗?

更新 1:

这是一个用于在我们的缓存之上标记的通用实现。在这一点上,我不确定我们最终是如何使用它的。这更像是我正在处理的PoC。一些数字试图回答评论中的一些问题:

  • 数量:我们每天有数千万独立访问者。但是,并非每个访问者存储在缓存中的所有项目都有标签。但这在不断变化。
  • 标签:标签是受管理的。目前有几十个标签。我们正在考虑将来支持自由文本标签。
  • 还没有测试我在这里建议的两种方法中的任何一种。我希望其中一个选项太糟糕了,甚至不是一个选项:)

更新 2:

经过一些试验和错误以及更多的研究,我放弃了 2)。Redis 客户端和输出缓冲区都有限制,这使得此选项不可用。您可以在此处和此处找到更多信息。我尝试了 1),它工作得很好。我什至将密钥的到期时间彼此相隔 5 毫秒,并且代码可以正确处理它。这可以是另一种选择。

另一个选项可以是@thepirat000建议的选项。我将这个答案标记为可接受的答案,但我也对他的建议进行了一些调整:我不想在每个标签操作的标签中进行维护,而是可以随机确定何时进行维护。这是一种足够好的方法,不使用发布/订阅或密钥空间通知。

为此使用密钥空间通知可能会产生太多开销。

为什么不将清理作为计划任务或定期任务进行清理,甚至在通过标记检索密钥时也是如此?

我在CachingFramework.Redis上做过类似的事情,在检索与标签相关的键时可以选择运行清理。此外,标记集 TTL 是它包含的键的 MAX(TTL)。

最新更新