Redis在具有15个较大JSON对象的列表上的查询时间超过1分钟(总共20MB)

时间:2015-08-08 15:50:37

标签: redis

我使用Redis缓存数据库插入。为此我创建了一个列表CACHE,我推送序列化的JSON列表。在伪代码中:

let entries = [{a}, {b}, {c}, ...];
redis.rpush("CACHE", JSON.stringify(entries));

想法是运行此代码一小时,然后再执行

let all = redis.lrange("CACHE", 0, LIMIT);
processAndInsert(all);
redis.ltrim("CACHE", 0, all.length);

现在的问题是每个entries可能相对较大(但远低于512MB /我读过的Redis限制)。 a, b, c中的每一个都是大约20个字节的对象,entries本身可以轻松拥有100k +对象/ 2MB。

我现在的问题是即使对于只有15个条目的非常短的CACHE个列表,简单的lrange也可能需要很长时间(!)甚至来自redis-cli(我的node.js实际上死于“致命错误:CALL_AND_RETRY_LAST分配失败 - 处理内存不足”,但这是一个侧面评论。)

列表的调试输出如下所示:

127.0.0.1:6379> debug object "CACHE"
Value at:00007FF202F4E330 refcount:1 encoding:linkedlist serializedlength:18104464 lru:12984004 lru_seconds_idle:1078

发生了什么事?为什么这么慢,我该怎么办呢?这似乎不是正常的慢度,似乎从根本上说是错误的。

我在相对硬核的Windows 10游戏机(i5,16GB RAM,840 EVO SSD,......)上使用本地Redis 2.8.2101(x64),ioredis 1.6.1,node.js 0.12

1 个答案:

答案 0 :(得分:1)

Redis擅长做大量的小型操作, 但在做少量的非常大的时候并不是那么好。操作。

我认为您应该重新评估您的算法,并尝试将数据拆分为较小的块。您不仅可以节省带宽,而且还不会长时间锁定您的redis实例。 Redis提供了许多数据结构,您应该可以使用它们对数据进行更细粒度的控制。

嗯,在这种情况下,由于您在本地运行redis,并且假设您没有运行除此代码之外的任何其他内容,我怀疑带宽和redis是问题所在。我更想到这一行:

JSON.stringify()

是你看到执行缓慢的主要原因。

20MB字符串的JSON序列化并不简单, 该过程需要分配许多小字符串,并且还必须遍历所有数组并单独检查每个项目。对于像这样的大型物体来说,所有这些都需要很长时间。

同样,如果您拆分数据并使用redis执行较小的操作,则根本不需要JSON序列化程序。