Redis通配符删除

时间:2015-09-25 05:32:41

标签: c# azure redis stackexchange.redis

我正在使用stackexchange redis提供程序,我正在尝试删除以某个键开头的所有键。

private readonly Lazy<IEnumerable<IServer>> allServers = new Lazy<IEnumerable<IServer>>(() => Connection.GetEndPoints().Select(s => Connection.GetServer(s)));
private const int DbId = 1;
private const int ScanPageSize = 1 << 14;

public void RemoveByPattern(string pattern)
{
    var keys = this.AllServers.Value.SelectMany(x => x.Keys(DbId, pattern + "*", ScanPageSize)).Distinct().ToArray();
    if (!keys.Any())
        return;
    this.Database.KeyDelete(keys);
}

^^这是我提出的方法,大部分时间都可以正常工作。但是一旦我对系统施加了一些负载,我就会遇到如下错误:

  System.TimeoutException: Timeout performing SCAN, inst: 0, mgr: Inactive, queue: 11, qu=11, qs=0, qc=0, wr=0/1, in=0/0
     at StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl (StackExchange.Redis.StrongName, Version=1.0.316.0, Culture=neutral, PublicKeyToken=c219ff1ca8c2ce46)
     at StackExchange.Redis.RedisServer.ExecuteSync (StackExchange.Redis.StrongName, Version=1.0.316.0, Culture=neutral, PublicKeyToken=c219ff1ca8c2ce46)
     at StackExchange.Redis.RedisBase+CursorEnumerable`1.GetNextPageSync (StackExchange.Redis.StrongName, Version=1.0.316.0, Culture=neutral, PublicKeyToken=c219ff1ca8c2ce46)
     at StackExchange.Redis.RedisBase+CursorEnumerable`1+CursorEnumerator.MoveNext (StackExchange.Redis.StrongName, Version=1.0.316.0, Culture=neutral, PublicKeyToken=c219ff1ca8c2ce46)
     at System.Linq.Enumerable+<SelectManyIterator>d__1`2.MoveNext (System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
     at System.Linq.Enumerable+<DistinctIterator>d__1`1.MoveNext (System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
     at System.Linq.Buffer`1..ctor (System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
     at System.Linq.Enumerable.ToArray (System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
     at Test.RedisCacheManager.RemoveByPattern (TestApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null)

有更好的方法吗? 我知道,如果我知道.net端的所有按键,我可以避免扫描。但不幸的是,在我的情况下,这并不是特别容易。

3 个答案:

答案 0 :(得分:1)

我回答了类似的问题here。您可以在StackExchange.Redis.StrongName v1.0.488。

中使用以下内容
        foreach (var ep in _muxer.GetEndPoints())
        {
            var server = _muxer.GetServer(ep);
            var keys = server.Keys(database: _redisDatabase, pattern: pattern + "*").ToArray();
            _db.KeyDeleteAsync(keys);
        }

_muxerConnectionMultiplexer

的实例

答案 1 :(得分:0)

您应该能够在某些 set 中存储部分密钥或相关密钥,然后扫描,而不是删除模式 (即{ {1}})使用页面删除全局键空间键。

不要尝试一次性删除数千个密钥:记住Redis是一个单线程解决方案,删除将阻止整个Redis服务器。

答案 2 :(得分:0)

有几个选项可以做你想要的,但我同意@Matías,因为你需要在SET中存储你想要删除的键。

如果您运行的是独立的Redis,最可靠的方法是在Lua脚本中执行添​​加/删除操作。但是如果您计划拥有Redis群集,则必须在客户端执行此操作。

例如:

public void SetValue(string key, string value)
{
    var batch = db.CreateBatch(); // You can use a transaction with CreateTransaction() if you are not in a cluster.
    batch.StringSetAsync(key, value);
    batch.SetAddAsync("to remove", key);
    batch.Execute();
}
public void RemoveAll()
{
    var item = db.SetPop("to remove");
    while (item.HasValue)
    {
        db.KeyDelete(item.ToString());
        item = db.SetPop("to remove");
    }
}