StackExchange Redis删除所有以开头的键

Tom*_*len 2 c# stackexchange.redis

我有一个格式的密钥:

Error.1
Error.24
Error.32
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

Dav*_*ack 9

Redis.StackExchange v2.1.0-preview.23 及更高版本中提供了带有C# 异步流的IAsyncEnumerable新版本。

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

我还应该指出,Redis 通配符支持允许非常灵活的模式。在我的实现中(如下),我只需要在密钥末尾有一个“*”,所以这就是它的编码目的。如果您需要额外的通配符支持,您可以在此处实现Redis 通配符支持的 glob 样式模式

  • h?llo 匹配 hello、hallo 和 hxllo
  • h*llo 匹配 hello 和 heeeello
  • h[ae]llo 匹配 hello 和 Hallo,但不匹配 hillo
  • h[^e]llo 匹配hallo, hbllo, ...但不匹配hello
  • h[ab]llo 匹配 Hallo 和 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;
    }
}
Run Code Online (Sandbox Code Playgroud)


Cri*_*ufu 5

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

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);
         }
    }
}
Run Code Online (Sandbox Code Playgroud)

以后编辑:

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

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

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

StackExchange.Redis server.Keys(模式:“ IsVerySlow *”)

  • @AaronNewton,redis是单线程的,因此您只需要一个连接。在应用启动时创建一个静态连接,然后将其永久保存。如果这样做的话,您将不需要使用,并且实际上也不需要,因为创建和处理连接非常昂贵,并且每毫秒都在缓存提供程序中。 (3认同)
  • [documentation](https://stackexchange.github.io/StackExchange.Redis/Basics)明确表示,多路复用器**应该存储和重用**,而不是每次都处置和重新创建。 (2认同)