首页 > 解决方案 > Redis StackExchange 存储 500k 个类

问题描述

我试图用 redis 代替现有的缓存系统,该系统基本上由Dictionary<id, class>. 我有大约 500k 个对象,并且正在使用 MsgPackObjectSerializer。我在尝试检索整个数据集时遇到了性能问题。

获取所有密钥需要几秒钟。

var keys = cacheClient.SearchKeys("ID:*").ToList();

并以这种方式使用 GetAll 方法:

cacheClient.GetAll<class>(keys).Values;

即使使用以下配置也会导致超时:

     var configOptions = new ConfigurationOptions();
     configOptions.EndPoints.Add("localhost:6379");
     configOptions.ClientName = "RedisClient";
     configOptions.ConnectTimeout = (int) TimeSpan.FromSeconds(5).TotalMilliseconds;
     configOptions.SyncTimeout = (int) TimeSpan.FromSeconds(5).TotalMilliseconds;
     configOptions.AbortOnConnectFail = false;
     configOptions.ResponseTimeout = (int) TimeSpan.FromSeconds(5).TotalMilliseconds;

我能够得到结果的唯一方法是通过这种方式:

var fromRedis = new ConcurrentDictionary<id, class>();
keys.AsParallel().ForAll(k =>
{
    var div = cacheClient.Get<class>(k);
    if (div != null)
    {
        fromRedis.TryAdd(k, div)
    }
});

这对我来说似乎不正确,而且非常慢。

必须有更好的方法来做到这一点,我没有看到。

更新:这比 keys.AsParallel 调用稍快。仍然需要6秒...

     var insListScan = new List<Task<RedisValue[]>>();

     foreach (var batch in server.Keys(0, "InstrumentSK:*").Batch(1000))
     {
        var tran = cacheClient.Database.CreateTransaction();
        insListScan.Add(tran.StringGetAsync(batch.ToArray()));
        tran.Execute();
     }

标签: cachingredisstackexchange.redis

解决方案


现在你正在寻找SCAN命令。

由于 StackExchange.Redis 的目标是集群等场景,因此了解哪些命令针对数据库(可以分布在多个节点上的逻辑数据库)以及哪些命令针对服务器非常重要。SCAN 命令针对单个服务器。

可以从 StackExchange.Redis 文档和使用 SCAN 的解决方法中找到详细说明。


推荐阅读