StackExchange.Redis扫描x密钥数量

时间:2018-07-25 15:03:05

标签: c# redis stackexchange.redis

我有一个具有数千个键的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个密钥吗?

谢谢

2 个答案:

答案 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不是存储数据的理想方式,它是 对于ExecuteScriptEvaluate,只需必要的