我正在尝试使用 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 Keyspace Notifications来防止过期的密钥永远留在我的标签集中(即使缓存中的每个项目都有默认的 TTL 集,我也不喜欢保留陈旧的数据)。
这些是我正在考虑的选项:
1) 订阅所有“过期”事件。
psubscribe '__keyevent@*:expired'
优点:
- 只有 1 个订阅者。
缺点:
- 由于并非所有项目都包含标签,因此我必须检查 mykey:tags ,如果存在则获取标签并从每个标签集中删除该项目。
- 这种方法的争用将随着存储中键的数量而增加。
2) 订阅那些只包含标签的键的所有事件。
psubscribe '__keyspace@*:mykey'
优点:
- 将为仅带有标签的项目创建订阅。
缺点:
- 必须有与每个订阅者相关的开销。
- 根据商店中标记商品的数量,订阅者的数量可以快速增长。
问题:
- 我应该实施哪个选项?我应该关注 2) 的订阅者数量还是 1) 的争论更重要?我找不到关于这个主题的任何建议。
- 最终的目标是在 Redis 集群上实现这一点。这是否会给实施增加任何额外的关注?
更新1:
这是在我们的缓存上进行标记的通用实现。在这一点上,我不确定我们最终是如何使用它的。这更像是我正在研究的 PoC。一些数字试图回答评论中的一些问题:
- 数量:我们每天有数千万的独立访问者。但是,并非每个访问者的缓存中存储的所有项目都有标签。但这种情况不断变化。
- 标签:标签被管理。目前有几十个标签。我们正在考虑在未来支持自由文本标签。
- 我没有测试我在这里建议的两种方法中的任何一种。我希望其中一个选项太糟糕了,甚至不是一个选项:)
更新 2:
经过一些试验和错误以及更多的研究,我放弃了2)。redis 客户端和输出缓冲区都有限制,这使得这个选项不可行。您可以在此处和此处找到更多信息。我试过1),它工作得很好。我什至将密钥的到期时间设置为彼此相距 5ms,并且代码可以正确处理它。这可以是一个替代方案。
@thepirat000 建议的另一种选择。我将此答案标记为已接受的答案,但我还对他的建议进行了一些调整:我不想在每个标签操作的标签中进行维护,而是我可以随机确定何时进行。这是一个足够好的方法,它不使用 pub/sub 也不使用键空间通知。