如何使用StackExchange.Redis删除所有匹配指定键模式的键?

3
我在 Redis 缓存中有大约 150,000 个键,需要删除其中 >95% 的键 - 包括特定键前缀匹配的所有键 - 作为缓存重建的一部分。我认为有三种方法可以实现这个需求:
  1. 使用 server.Keys(pattern) 提取与我的前缀模式相匹配的整个键列表,并遍历这些键,逐个调用 KeyDelete 进行删除。
  2. 维护一个 Redis 集合中的键列表 - 每次插入值时,同时将键插入相应的键集合中,然后检索这些集合而不是使用 Keys。这样可以避免昂贵的 Keys() 调用,但仍然需要逐个删除数万条记录。
  3. 将所有易失数据隔离到一个指定的编号数据库中,在缓存重建开始时完全清除该数据库。
我正在使用 .NET 和 StackExchange.Redis 客户端 - 我看到其他解决方案使用 CLI 或依赖于 Lua 脚本,但似乎没有解决这个特定用例的解决方案 - 我错过了什么,或者 Redis 不适合处理这种需求?
(背景:Redis 在 Microsoft Dynamics CRM API 前作为视图模型使用,因此缓存在第一次运行时通过从 CRM 中提取约 100K 条记录来填充,并通过在 CRM 内部发布通知来保持同步。数据无限期缓存在 Redis 中,我们在处理一种特定情况,即 CRM 插件在一段时间内失败,导致缓存漂移并最终需要我们清除和重建缓存。)

对于选项2,您可以使用标记机制来使其失效,例如LUA实现的这个,或者支持集群的这个 - thepirat000
2个回答

1

选项2和3都是合理的。

避免选项1。KEYS确实很慢,随着键空间的增长,它只会变得更慢。

通常我会选择选项2(不使用LUA),包括LUA会增加支持解决方案的学习曲线 - 当然,在有正当理由并且假设其存在是明确/记录的情况下,这也是可以接受的。但选项3绝对可以成为一个竞争者,快速而简单,只要您能确定不会超过配置的数据库限制。


这对您有帮助吗?您采用了哪种解决方案?谢谢。 - Joseph Simpson

1
使用scanStream而不是keys,它会像魔术一样工作。 文档 - https://redis.io/commands/scan 下面的代码可以让你得到以LOGIN::开头的键数组,你可以循环遍历该数组并执行redis DEL命令来删除相应的键。
在nodejs中的示例代码:
const redis = require('ioredis');
    let stream = redis.scanStream({
        match: "LOGIN::*"
    });
     stream.on("data", async (keys = []) => {
                        let key;
                        for (key of keys) {
                            if (!keysArray.includes(key)) {
                                await keysArray.push(key);
                            }
                        }
                    });
                    stream.on("end", () => {
                        res(keysArray);
                    });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接