我有一个具有数千个键的redis数据库,并且我当前正在运行以下行以获取所有键:
string[] keysArr = keys.Select(key => (string)key).ToArray();
但是因为我有很多键,所以需要很长时间。我想限制正在读取的键的数量。因此,我试图运行一个执行命令,一次可以获取100个键:
var keys = Redis.Connection.GetDatabase(dbNum).Execute("scan", 0, "count", 100);
此命令成功运行了该命令,但是由于它是私有的,因此无法访问该值,并且即使RedisResult类为它提供了显式的强制转换,也无法将其强制转换:
public static explicit operator string[] (RedisResult result);
有什么想法可以从redis一次获取x个密钥吗?
谢谢
答案 0 :(得分:1)
我将使用Microsoft here概述的.Take()方法。
从a的开头返回指定数量的连续元素 顺序。
它看起来像这样:
//limit to 100
var keysArr = keys.Select(key => (string)key).Take(100).ToArray();
答案 1 :(得分:1)
SE.Redis在.Keys()
API上有一个IServer
方法,该方法完全封装了SCAN
的语义。如果可能的话,只使用此方法,并一次使用100个数据。编写批处理功能通常很容易,即
ExecuteInBatches(server.Keys(), 100, batch => DoSomething(batch));
具有:
public void ExecuteInBatches<T>(IEnumerable<T> source, int batchSize,
Action<List<T>> action)
{
List<T> batch = new List<T>();
foreach(var item in source) {
batch.Add(item);
if(batch.Count == batchSize) {
action(batch);
batch = new List<T>(); // in case the callback stores it
}
}
if (batch.Count != 0) {
action(batch); // any leftovers
}
}
枚举器会担心前进的光标。
您可以使用Execute
,但是:要做很多工作!另外,SCAN
对每页将返回多少没有保证。它可以是零-可以是您要求的3倍。只是指导。
顺便说一句,强制转换失败的原因是SCAN
不返回 a string[]
-它返回包含两个项的数组,其中第一个是“下一个”光标,第二个是按键。所以也许:
var arr = (RedisResult[])server.Execute("scan", 0);
var nextCursor = (int)arr[0];
var keys = (RedisKey[])arr[1];
但是所有这一切都是在重新实现IServer.Keys
,这是很困难的方式(而且效率显着降低-ServerResult
不是存储数据的理想方式,它是 对于Execute
和ScriptEvaluate
,只需必要的。