【问题标题】:StackExchange Redis delete all keys that start withStackExchange Redis 删除所有以
【发布时间】:2017-05-06 00:02:43
【问题描述】:

我有一个格式为:

Error.1
Error.24
Error.32

使用StackExchange.Redis,我将如何在与Error. 格式匹配的所有键上使用KeyDelete

在另一个答案中,我看到了 LUA 脚本:

EVAL "return redis.call('del', unpack(redis.call('keys', ARGV[1])))" 0 Error.*

但我不确定如何使用 Database.ScriptEvaluate() 调用它

【问题讨论】:

    标签: c# stackexchange.redis


    【解决方案1】:

    只需获取与模式匹配的所有键,迭代和删除,如下所示:

    using (var redisConnection = ConnectionMultiplexer.Connect(...))
    {
        var server = redisConnection.GetServer(endpoint:...);
    
        if (server != null)
        {
             foreach (var key in server.Keys(pattern: "Error.*"))
             {
                   redisConnection.Database.KeyDelete(key);
             }
        }
    }
    

    后期编辑:

    设置 Redis 连接的示例:https://gist.github.com/cristipufu/9ad47caf3dba60d712484d0c880597b9

    多路复用器应该被存储和重复使用,而不是每次都丢弃和重新创建。 https://stackexchange.github.io/StackExchange.Redis/Basics

    通过调整/指定 Keys 调用的 pageSize 参数可以显着提高性能。它的默认值为 10。尝试 1,000。

    StackExchange.Redis server.Keys(pattern:"IsVerySlow*")

    【讨论】:

    • 请注意。此代码有效,但是您应该有一个 using 块用于连接,例如using (var redisConnection = ConnectionMultiplexer.Connect(...)) { /* Other code inside the using block */ }。否则,您的连接可能无法正确处理,并且您最终会遇到线程饥饿,就像我刚刚在我的一个应用程序中遇到的那样。我打开了任务管理器,在调试时,我实际上可以看到线程池随着该应用程序中的每个请求而增长。
    • @AaronNewton ,redis 是单线程的,所以你只需要一个连接。在应用启动时创建一个静态连接,然后永久保留。如果这样做,您将不需要使用,实际上也不应该使用,因为创建和处理连接的成本很高,而且缓存提供程序中的每一毫秒都很重要。
    • documentation 明确表示多路复用器应该被存储和重复使用,而不是每次都丢弃和重新创建。
    • 这不是我第一次看到这个解决方案,但它对我来说似乎很笨重。您必须从特定服务器请求密钥?集群时会出现问题吗?另外,这种方法有什么显着的性能影响吗?
    • 通过调整/指定pageSize 调用的pageSize 参数可以显着提高性能。它的默认值为 10。尝试 1,000。以下是信息来源:stackoverflow.com/questions/26438736/…
    【解决方案2】:

    在 Redis.StackExchange v2.1.0-preview.23 及更高版本中提供具有 C# Asynchronous Streaming via IAsyncEnumerable 的新版本。

    注意:如果您的 Redis 实例支持该功能,则此版本使用 SCAN 而不是 KEYS。这是一个巨大的性能提升。您还应该确保您的 ConnectionMultiplexer 实例是单例 - 即在应用程序的生命周期中使用相同的实例。

    我还应该指出,Redis 通配符支持允许非常灵活的模式。在我的实现中(如下),我只需要在键的末尾有一个“*”,这就是它的全部编码。如果你需要额外的通配符支持,你可以在这里实现Redis wildcard supported glob-style patterns

    • h?llo 匹配 hello、hallo 和 hxllo
    • h*llo 匹配 hllo 和 heeeello
    • h[ae]llo 匹配 hello 和 halo,但不匹配 hillo
    • h[^e]llo 匹配 halo, hbllo, ... 但不匹配 hello
    • h[a-b]llo 匹配 halo 和 hbllo

    如果您想逐字匹配特殊字符,请使用 \ 转义它们。

    using Microsoft.Extensions.Caching.Distributed;
    using StackExchange.Redis;
    
    private readonly IDistributedCache _cache;
    private readonly IConnectionMultiplexer _connectionMultiplexer;
    
    public CacheRepository(IDistributedCache cache, IConnectionMultiplexer connectionMultiplexer)
    {
        _cache = cache;
        _connectionMultiplexer = connectionMultiplexer;
    }
    
    public async Task RemoveWithWildCardAsync(string keyRoot)
    {
        if (string.IsNullOrWhiteSpace(keyRoot))
            throw new ArgumentException("Value cannot be null or whitespace.", nameof(keyRoot));
    
        // get all the keys* and remove each one
        await foreach (var key in GetKeysAsync(keyRoot + "*"))
        {
            await _cache.RemoveAsync(key);
        }
    }
    
    public async IAsyncEnumerable<string> GetKeysAsync(string pattern)
    {
        if (string.IsNullOrWhiteSpace(pattern))
            throw new ArgumentException("Value cannot be null or whitespace.", nameof(pattern));
    
        foreach (var endpoint in _connectionMultiplexer.GetEndPoints())
        {
            var server = _connectionMultiplexer.GetServer(endpoint);
            await foreach (var key in server.KeysAsync(pattern: pattern))
            {
                yield return key.ToString();
            }
        }
    }
    
    public IEnumerable<RedisFeatures> GetRedisFeatures()
    {
        foreach (var endpoint in _connectionMultiplexer.GetEndPoints())
        {
            var server = _connectionMultiplexer.GetServer(endpoint);
            yield return server.Features;
        }
    }
    

    【讨论】:

    • 嗨@Dave,你有这方面的性能基准吗?谢谢。
    • 对不起 - 我没有任何基准。如果您最终创建了一些,请分享它们。
    • @DaveBlack 在 Microsoft.extensions.caching.stackexchangeredis.3.1.18 中找不到 KeysAsync 方法。只有返回 IEnumerable 的 Keys 方法可用。您的意思是 KeysAsnyc 在 Redis.StackExchange v2.1.0-preview.23 中可用?
    • @Rasel - 是的,Redis.StackExchange。可能他们已将其添加到 Microsoft.Extensions.Caching.StackExchangeRedis 的 .NET 6 版本中,但我没有检查。
    • @DaveBlack 我正在使用 .net Core 3.1 和 Microsoft.extensions.caching.stackexchangeredis.3.1.18。顺便说一句,我在运行时面临的另一个问题是 Autofac 无法为 IConnectionMultiplexer 注入实例。你能说一下我在启动时需要在 IServiceCollection 中添加什么吗?
    【解决方案3】:

    我花了一些时间没有得到任何密钥using accepted answer

    对于模式,使用类似的东西。

    server.Keys(pattern: "*Error.*")
    

    您应该在图案前后添加星号。

    【讨论】:

      猜你喜欢
      • 2022-01-12
      • 2016-07-27
      • 2016-02-07
      • 2017-08-01
      • 2020-02-15
      • 1970-01-01
      • 2011-10-14
      • 2019-08-29
      • 2012-04-07
      相关资源
      最近更新 更多