Redis 键空间通知 - 订阅者数量与争用
Redis Keyspace Notifications - No. of Subscribers vs Contention
我正在尝试使用 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) 订阅所有 "expired" 事件。
psubscribe '__keyevent@*:expired'
优点:
- 只有 1 个订阅者。
缺点:
- 由于并非所有项目都包含标签,因此我必须检查 mykey:tags
如果存在,则获取标签并从每个标签集中删除该项目。
- 这个方法的竞争会随着密钥的数量增加而增加
在店里。
2) 为那些只包含标签的键订阅所有事件。
psubscribe '__keyspace@*:mykey'
优点:
- 将为那些只有标签的项目创建订阅。
缺点:
- 必须有与每个订户关联的开销。
- 订户数量可以根据数量快速增长
商店中标记的商品数量。
问题:
- 我应该实施哪个选项?我应该担心
2) 上的订户数量或 1) 上的争用更大
交易?我找不到关于这个主题的任何建议。
- 最后的目标是在 Redis 集群上实现它。这是否添加
对实施有任何额外的关注吗?
更新 1:
这是在缓存顶部进行标记的通用实现。我现在不确定我们最终是如何使用它的。这更像是我正在研究的 PoC。一些数字试图回答评论中的一些问题:
- 流量:我们每天有数千万独立访客。不过,并非每个访问者存储在缓存中的所有项目都有标签。但这在不断变化。
- 标签:标签被管理。目前有几十个标签。我们正在考虑在未来支持自由文本标签。
- 我还没有测试我在这里建议的两种方法中的任何一种。我希望其中一个选项非常糟糕,甚至不是一个选项:)
更新 2:
经过反复试验和更多研究后,我放弃了 2)。 Redis 客户端和输出缓冲区都有限制,这使得该选项无法使用。您可以找到更多信息 here and here。
我尝试了 1) 并且效果很好。我什至将密钥的到期时间设置为 5 毫秒,并且代码可以正确处理它。这可以作为替代方案。
@thepirat000 建议的另一个选项。我将这个答案标记为已接受的答案,但我也对他的建议做了一点调整:我不想在每个标签操作中都对标签进行维护,而是我可以随机确定何时进行维护。这是一个很好的方法,它不使用 pub/sub 也不使用键空间通知。
为此使用键空间通知可能会产生过多的开销。
为什么不将清理作为计划任务或重复任务进行,或者甚至在通过标签检索密钥时进行清理?
我在 CachingFramework.Redis 上做过类似的事情,其中在检索与标签相关的键时可以选择 运行 进行清理。此外,标签集 TTL 是它包含的键的 MAX(TTL)。
我正在尝试使用 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) 订阅所有 "expired" 事件。
psubscribe '__keyevent@*:expired'
优点:
- 只有 1 个订阅者。
缺点:
- 由于并非所有项目都包含标签,因此我必须检查 mykey:tags 如果存在,则获取标签并从每个标签集中删除该项目。
- 这个方法的竞争会随着密钥的数量增加而增加 在店里。
2) 为那些只包含标签的键订阅所有事件。
psubscribe '__keyspace@*:mykey'
优点:
- 将为那些只有标签的项目创建订阅。
缺点:
- 必须有与每个订户关联的开销。
- 订户数量可以根据数量快速增长 商店中标记的商品数量。
问题:
- 我应该实施哪个选项?我应该担心 2) 上的订户数量或 1) 上的争用更大 交易?我找不到关于这个主题的任何建议。
- 最后的目标是在 Redis 集群上实现它。这是否添加 对实施有任何额外的关注吗?
更新 1:
这是在缓存顶部进行标记的通用实现。我现在不确定我们最终是如何使用它的。这更像是我正在研究的 PoC。一些数字试图回答评论中的一些问题:
- 流量:我们每天有数千万独立访客。不过,并非每个访问者存储在缓存中的所有项目都有标签。但这在不断变化。
- 标签:标签被管理。目前有几十个标签。我们正在考虑在未来支持自由文本标签。
- 我还没有测试我在这里建议的两种方法中的任何一种。我希望其中一个选项非常糟糕,甚至不是一个选项:)
更新 2:
经过反复试验和更多研究后,我放弃了 2)。 Redis 客户端和输出缓冲区都有限制,这使得该选项无法使用。您可以找到更多信息 here and here。 我尝试了 1) 并且效果很好。我什至将密钥的到期时间设置为 5 毫秒,并且代码可以正确处理它。这可以作为替代方案。
@thepirat000 建议的另一个选项。我将这个答案标记为已接受的答案,但我也对他的建议做了一点调整:我不想在每个标签操作中都对标签进行维护,而是我可以随机确定何时进行维护。这是一个很好的方法,它不使用 pub/sub 也不使用键空间通知。
为此使用键空间通知可能会产生过多的开销。
为什么不将清理作为计划任务或重复任务进行,或者甚至在通过标签检索密钥时进行清理?
我在 CachingFramework.Redis 上做过类似的事情,其中在检索与标签相关的键时可以选择 运行 进行清理。此外,标签集 TTL 是它包含的键的 MAX(TTL)。