17

我是redis的新手,所以我做错了,我敢肯定:

我在 Azure Redis 中存储了大约 16,000 个键/值。

我使用以下内容编写键/值

      foreach (var worksheet in wksList)
      {
        var wksYYMM = string.Format("{0}{1:00}", worksheet.ReviewDt.Year, worksheet.ReviewDt.Month);
        var wksKey = string.Format("{0}:{1}:{2}", provCode, wksYYMM, worksheet.AcctNbr);
        string jsonStr = JsonConvert.SerializeObject( MakeWsListDto(worksheet, provCoderList, rvrList));
        cache.StringSet(wksKey, jsonStr);
      }

所以我的钥匙看起来像这样:“AP:201401:AZ5798BK”

当我尝试查找时:

    var keys = server.Keys(pattern: "AP:201401:*"); // returns in milliseconds
    var keyAry = keys.ToArray(); // returns in over one minute
    (note: this returns 12 keys)

返回密钥需要 1 分 12 秒。一旦我有了密钥,就需要几毫秒来检索这些密钥的值。如果我遍历键的值并返回值,我会得到类似的结果。我做了一个 ToArray() 只是为了隔离问题。

如果我在 redis-cli.exe 中尝试相同的查询,它会在几毫秒内返回。

我是否错误地使用了这个命令?

4

2 回答 2

31

server.Keys根据服务器版本自动选择KEYS和首选。SCAN我怀疑正在发生的事情是您使用SCAN的页面尺寸太小。页面大小有一个可选参数。尝试指定比默认值大得多的值 - 数百、数千等。如果未指定,页面大小将使用 RedisSCAN 默认值10,这可能会导致需要大量往返。

于 2014-10-18T13:17:03.737 回答
11

不要使用KEYS- 这是一个阻塞命令,它将在运行时使您的 Redis 服务器对其他请求不可用。引用命令的文档

警告:将 KEYS 视为仅应极其小心地在生产环境中使用的命令。当它针对大型数据库执行时,它可能会破坏性能。此命令用于调试和特殊操作,例如更改键空间布局。不要在常规应用程序代码中使用 KEYS。如果您正在寻找一种在键空间子集中查找键的方法,请考虑使用 SCAN 或集合。

如果您仔细阅读警告,您会注意到段落末尾的推荐方法,即使用SCAN或 Redis 的集合。SCAN 是非阻塞的,但由于您的问题表明您对性能很感兴趣,因此我建议使用集合。

这个想法是维护一个 Redis 集,其中包含与该“模式”关联的所有键名,因此在您的示例中,您必须SADD AP:201401 AP:201401:AZ5798BK在调用 之后执行 StackExchange.Redis 等效项cache.SetString,例如:

cache.SetAdd(wksYYMM, wksKey);

免责声明:我不是 C# 程序员,对 StackExchange.Redis 也不太熟悉(抱歉,Marc ;))

现在,代替 KEYS 或 SCAN 来获取您的密钥,只需执行SMEMBERS AP:201401或可能:

var keys = cache.Members(wksYYMM);

奖励:由于您实际上对这些键的值感兴趣,因此您可以使用 Redis 的 Lua 脚本根据集合的成员获取键值,或者只使用SORT

纯 Redis:

SORT AP:201401 BY nosort GET *`

C# & StackExchange.Redis:

vals = cache.Sort(wksYYMM, by = "nosort", get = "*");
于 2014-10-18T11:50:06.847 回答