我使用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
答案 0 :(得分:1)
Redis擅长做大量的小型操作, 但在做少量的非常大的时候并不是那么好。操作。
我认为您应该重新评估您的算法,并尝试将数据拆分为较小的块。您不仅可以节省带宽,而且还不会长时间锁定您的redis实例。 Redis提供了许多数据结构,您应该可以使用它们对数据进行更细粒度的控制。
嗯,在这种情况下,由于您在本地运行redis,并且假设您没有运行除此代码之外的任何其他内容,我怀疑带宽和redis是问题所在。我更想到这一行:
JSON.stringify()
是你看到执行缓慢的主要原因。
20MB字符串的JSON序列化并不简单, 该过程需要分配许多小字符串,并且还必须遍历所有数组并单独检查每个项目。对于像这样的大型物体来说,所有这些都需要很长时间。
同样,如果您拆分数据并使用redis执行较小的操作,则根本不需要JSON序列化程序。