StackExchange.Redis 扫描 x 个键
StackExchange.Redis Scan x amount of keys
我有一个包含数千个键的 Redis 数据库,我目前正在 运行 执行以下行以获取所有键:
string[] keysArr = keys.Select(key => (string)key).ToArray();
但是因为我有很多钥匙,所以需要很长时间。我想限制正在读取的键数。所以我正在尝试 运行 执行命令,一次获得 100 个键:
var keys = Redis.Connection.GetDatabase(dbNum).Execute("scan", 0, "count", 100);
此命令成功 运行s 命令,但是无法访问该值,因为它是私有的,并且即使 RedisResult 类为其提供显式转换也无法对其进行转换:
public static explicit operator string[] (RedisResult result);
有什么想法可以从 redis 中一次获取 x 个键吗?
谢谢
我会使用微软概述的 .Take() 方法 here。
Returns a specified number of contiguous elements from the start of a
sequence.
看起来像这样:
//limit to 100
var keysArr = keys.Select(key => (string)key).Take(100).ToArray();
SE.Redis 在 IServer
API 上有一个 .Keys()
方法,它完全封装了 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
不保证每页将 return 编辑多少;它可以是零——它可以是你要求的 3 倍。仅供参考。
顺便说一下,转换失败的原因是因为 SCAN
没有 return string[]
- 它 returns 包含两项的数组,第一项是 "next" 光标,第二项是键。所以也许:
var arr = (RedisResult[])server.Execute("scan", 0);
var nextCursor = (int)arr[0];
var keys = (RedisKey[])arr[1];
但是所有这一切都在重新实现 IServer.Keys
,这是一种困难的方式(而且效率明显较低 - ServerResult
不是 的理想方式存储数据,在Execute
和ScriptEvaluate
的情况下是必需的。
我有一个包含数千个键的 Redis 数据库,我目前正在 运行 执行以下行以获取所有键:
string[] keysArr = keys.Select(key => (string)key).ToArray();
但是因为我有很多钥匙,所以需要很长时间。我想限制正在读取的键数。所以我正在尝试 运行 执行命令,一次获得 100 个键:
var keys = Redis.Connection.GetDatabase(dbNum).Execute("scan", 0, "count", 100);
此命令成功 运行s 命令,但是无法访问该值,因为它是私有的,并且即使 RedisResult 类为其提供显式转换也无法对其进行转换:
public static explicit operator string[] (RedisResult result);
有什么想法可以从 redis 中一次获取 x 个键吗?
谢谢
我会使用微软概述的 .Take() 方法 here。
Returns a specified number of contiguous elements from the start of a sequence.
看起来像这样:
//limit to 100
var keysArr = keys.Select(key => (string)key).Take(100).ToArray();
SE.Redis 在 IServer
API 上有一个 .Keys()
方法,它完全封装了 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
不保证每页将 return 编辑多少;它可以是零——它可以是你要求的 3 倍。仅供参考。
顺便说一下,转换失败的原因是因为 SCAN
没有 return string[]
- 它 returns 包含两项的数组,第一项是 "next" 光标,第二项是键。所以也许:
var arr = (RedisResult[])server.Execute("scan", 0);
var nextCursor = (int)arr[0];
var keys = (RedisKey[])arr[1];
但是所有这一切都在重新实现 IServer.Keys
,这是一种困难的方式(而且效率明显较低 - ServerResult
不是 的理想方式存储数据,在Execute
和ScriptEvaluate
的情况下是必需的。