StackExchange.Redis 扫描 x 数量的密钥

Per*_*son 5 c# redis stackexchange.redis

我有一个 redis db,它有数千个键,我目前正在运行以下行来获取所有键:

string[] keysArr = keys.Select(key => (string)key).ToArray();
Run Code Online (Sandbox Code Playgroud)

但是因为我有很多钥匙,这需要很长时间。我想限制正在读取的键数。所以我试图运行一个执行命令,我一次得到 100 个键:

var keys = Redis.Connection.GetDatabase(dbNum).Execute("scan", 0, "count", 100);
Run Code Online (Sandbox Code Playgroud)

此命令成功运行该命令,但是无法访问该值,因为它是私有的,并且即使 RedisResult 类为其提供了显式转换,也无法转换它:

public static explicit operator string[] (RedisResult result);
Run Code Online (Sandbox Code Playgroud)

有什么想法可以一次从 redis 获取 x 数量的密钥吗?

谢谢

Mar*_*ell 6

SE.Redis.Keys()IServerAPI上有一个方法,它完全封装了SCAN. 如果可能的话,就用这个方法,一次消耗100条数据。编写批处理函数通常很容易,即

ExecuteInBatches(server.Keys(), 100, batch => DoSomething(batch));
Run Code Online (Sandbox Code Playgroud)

和:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

枚举器将担心推进光标。


可以使用Execute,但是:这是很多工作!此外,SCAN不保证每页将返回多少;它可以是零 - 它可以是您要求的 3 倍。它只是......指导。

顺便说一下,转换失败的原因是因为SCAN 不返回a string[]- 它返回一个包含两个项目的数组,其中第一个是“下一个”光标,第二个是键。所以也许:

var arr = (RedisResult[])server.Execute("scan", 0);
var nextCursor = (int)arr[0];
var keys = (RedisKey[])arr[1];
Run Code Online (Sandbox Code Playgroud)

但是,这一切正在做的是重新实施IServer.Keys,硬盘的方式(和显著较低的效率-ServerResult不是存储数据的理想方式,它只是必要的情况下ExecuteScriptEvaluate)。


Aus*_*Joe 1

我将使用 Microsoft此处概述的 .Take() 方法。

从序列开头返回指定数量的连续元素。

它看起来像这样:

//limit to 100
var keysArr = keys.Select(key => (string)key).Take(100).ToArray();
Run Code Online (Sandbox Code Playgroud)

  • 使用“skip”和“take here”来获取页面...坦率地说...在这种情况下会非常糟糕;该意图无法向服务器表达,因此您正在实现三角查询(意思是:第一个项目很便宜,下一页更昂贵,依此类推......直到最后一页非常昂贵)。这不是解决这个问题的好方法*在这种特定情况下* (5认同)