我正在使用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端的所有按键,我可以避免扫描。但不幸的是,在我的情况下,这并不是特别容易。
答案 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);
}
_muxer
是ConnectionMultiplexer
答案 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");
}
}