Redis 1+;对包含15个较大JSON对象的列表的最小查询时间(总计20MB)
我使用Redis缓存数据库插入。为此,我创建了一个列表Redis 1+;对包含15个较大JSON对象的列表的最小查询时间(总计20MB),redis,Redis,我使用Redis缓存数据库插入。为此,我创建了一个列表缓存,将序列化的JSON列表推送到其中。在伪代码中: let entries = [{a}, {b}, {c}, ...]; redis.rpush("CACHE", JSON.stringify(entries)); 我们的想法是运行这段代码一个小时,然后稍后再执行一次测试 let all = redis.lrange("CACHE", 0, LIMIT); processAndInsert(all); redis.ltrim("CACH
缓存,将序列化的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);
现在的问题是,每个条目可以相对较大(但远低于512MB/我读到的Redis限制)。a,b,c
中的每一个都是一个大约20字节的对象,而条目本身可以轻松地拥有100k+对象/2MB
我现在的问题是,即使是非常短的缓存
只列出了15个条目,一个简单的lrange
也可能需要很多分钟(!),即使是从redis cli
(我的node.js
实际上会因“致命错误:调用和重试上次分配失败-内存不足”而死亡,但这只是一个旁注)
列表的调试输出如下所示:
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。Redis擅长做很多小操作,
但不太擅长做少量“非常大”的业务
我认为您应该重新评估您的算法,并尝试将数据分成更小的块。不仅可以节省带宽,而且不会长时间锁定redis实例。
Redis提供了许多数据结构,您应该能够使用它们对数据进行更精细的控制
不过,在这种情况下,由于您在本地运行redis,并且假设您只运行此代码,那么我怀疑带宽和redis是否是问题所在。我更倾向于这样想:
JSON.stringify()
是你看到执行缓慢的罪魁祸首
20MB字符串的JSON序列化并不简单,
该过程需要分配许多小字符串,还必须遍历所有数组并逐个检查每个项目。对于像这样的大物体来说,所有这些都需要很长时间
同样,如果您正在分解数据,并使用redis执行较小的操作,则根本不需要JSON序列化程序 您是否考虑过使用redis的Hash
数据类型,而不是使用JSON.stringify()
?您可以使用MULTI命令单独保存所有哈希,然后将这些哈希的键存储在列表中。(多重指挥将在一次往返中完成)。嗯,这会带来什么好处?难道我不应该在RPUSH中使用MULTI吗?这就是我的意思,抱歉,首先使用MULTI命令保存散列,然后将它们的键添加到列表中。但是,我不得不问,是否有理由将整个缓存存储在一个密钥中,然后每次都检索整个缓存?传输非常大的数据可能会带来巨大的性能成本。也许可以在这里添加SLOWLOG GET
的输出。我刚刚测试了它,结果如下(在我5岁的旧笔记本上):创建(107毫秒),大小:2097152个元素
,字符串化(2043毫秒),大小:228589569字节
,转换回(3527毫秒),大小:2097152个元素
。(guid()。我刚刚意识到这些时间是200MB,而不是20MB。好吧,200MB可能会把你推到Redis的极限。不过,您需要重新构建算法。保存所有内容和恢复所有内容是不可扩展的。