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 不是 的理想方式存储数据,在ExecuteScriptEvaluate的情况下是必需的