如何从 Redis 获取一组特定的键

How to get a specific set of keys from Redis

我有一份 keys 的列表,我想从 Redis 中获取。我写了一个这样的函数,但它 return 包含所有内容:

    public IOrderedEnumerable<Fields> GetValues(List<string> symbols)
    {
        var retVal = new List<Fields>();

        var patternStr = "[";

        int count = 0;
        foreach (var symbol in symbols)
        {
            patternStr += (symbol);

            if (++count != symbols.Count)
            {
                patternStr += ", ";
            }
        }

        patternStr += "]*";

        foreach (var ep in redis.GetEndPoints())
        {
            var server = redis.GetServer(ep);
            var keysList = server.Keys(database: 0, pattern: patternStr).ToList();

            var keys = keysList.ToArray();

            Console.WriteLine("Number of Symbols in this range{0} ", keys.Length);

            foreach (var rk in keys)
            {
                var myValTask = db.StringGetAsync(rk.ToString());
                var myVal = myValTask.Result;
                var jsonStr = myVal.ToString();
                ...

            }
            ...
         }

         ...

我认为这部分代码有问题。我只想要 Redis 到 return subsetkeys,并且我正在通过用“,”分隔它们来构建一个模式:

    var patternStr = "[";

    int count = 0;
    foreach (var symbol in symbols)
    {
        patternStr += (symbol);

        if (++count != symbols.Count)
        {
            patternStr += ", ";
        }
    }

    patternStr += "]*";

我知道我可以获取所有密钥,然后在获取后对其进行过滤,但我想避免网络抖动...

编辑 1

顺便说一句,按键看起来像这样:

127.0.0.1:6379> keys *
  1) "BBWI_2022-08-19"
  2) "ABBV_2023-01-20"
  3) "ZTS_2022-10-21"

如果我没理解错的话,你有一组离散的键,你想在一个批次中获取。如果是这样,您可以通过传递 RedisKey[] array to StringGetAsync:

来获取所有项目(在合理范围内,一次说 < 1000)
var keys = symbols.Select(symbol => (RedisKey)symbol).ToArray();
var values = await db.StringGetAsync(keys);
// .. use values

你可以像这样在redis服务器上使用Scan命令:

 public async Task<List<string>> ScanKeysAsync(string match, string count)
        {
            var schemas=new List<string>();
            int nextCursor = 0;
            do
            {
                RedisResult redisResult =await _redisServer.ExecuteAsync("SCAN", nextCursor.ToString(), "MATCH", match, "COUNT", count);
                var innerResult = (RedisResult[])redisResult;

                nextCursor = int.Parse((string)innerResult[0]);

                List<string> resultLines = ((string[])innerResult[1]).ToList();
                schemas.AddRange(resultLines);
            }
            while (nextCursor != 0);

            return schemas;
        }

在你的情况下是这样的:

var keys=await ScanKeysAsync("BBWI*",10);//return max 10 occurance of pattern

但我建议在非常特殊的情况下使用Scan,因为它充当游标并会在redis中的所有键之间迭代以找到匹配项,另请阅读此https://redis.io/commands/scan

测试

 var redis = scope.ServiceProvider.GetRequiredService<IDatabase>();

await redis.StringSetAsync("BBWI_2022-08-19", "test1",TimeSpan.FromMinutes(5));
await redis.StringSetAsync("BBWI_20fd22-08-19", "test2", TimeSpan.FromMinutes(5));
await redis.StringSetAsync("ABBV_2023-08-19", "test3", TimeSpan.FromMinutes(5));

var foundKeys = await ScanKeysAsync("BBW*", "10");
//BBWI_2022-08-19
//BBWI_20fd22-08-19