Redis性能问题?

6
我想对Redis进行一些重负载测试,以了解其上限。首先,我使用大小为32个字符左右的50,000和100,000个键进行加载。两种键的大小都不超过8-15秒。现在我尝试将4kb的数据作为每个键的值。前面的10000个键只需要800毫秒设置完成。但从那时起,速度逐渐变慢,直到设置完整个50,000个键,需要大约40分钟。我使用NodeJs和node_redis(Mranney)来加载数据库。我是否有什么错误,或者Redis在处理4KB大小的大值时确实很慢?
我发现一个更让人担忧的问题是,当我运行另一个客户端并行更新键时,第二个客户端可以在8秒钟内完成加载50000个具有4kb值的键,而第一个客户端则永远无法完成。这是Node还是redis库中的错误?这是令人担忧的,生产环境下不能接受。

嗯...我安装了 hiredis,但我不知道当我执行 require('redis') 时它是否会自动加载到程序中。这是问题吗? - Lalith
要验证您是否已安装 hiredis 模块,可以运行 node,然后执行 require("hiredis") - Matt Ranney
3个回答

5

如果您需要从Node向Redis进行批量写入,您需要获取某种类型的背压。默认情况下,Node将队列中的所有写操作,并且不对传出队列大小设置上限。

node_redis具有“drain”事件,您可以侦听该事件以实现一些基本的背压机制。


嗨,马特,我尝试查看client.command_queue.length并停止直到我收到“drain”事件。但是client.command_queue.length始终为0。因此,我正在检查client.offline_queue.length,它给我正确的数字,但是drain事件只触发一次。我会再试一次并带上代码回来。谢谢。 - Lalith
我在这里附上了代码 https://gist.github.com/945441 。这似乎不是反压的正确方式? - Lalith
2
这里有几个不同的问题。第一个是预连接命令已排队等待。第二个是一旦您建立了连接,就会维护另一个队列,用于发送但尚未收到回复的命令。我在这里添加了一个通用的方式来处理这两种情况:https://github.com/mranney/node_redis/blob/master/examples/backpressure_drain.js - Matt Ranney

3

默认的Redis配置并不适用于这种使用方式。我怀疑你的Redis正在使用32字节的页面大小交换到磁盘,这意味着每个添加的键都必须找到128个连续的空闲页面,并且可能会使用系统VM或需要大量扩展交换文件。

当你更新一个键时,空间已经分配好了,所以你不会看到任何性能问题。


这只是为了测试目的,所以我不太在意。但如果这样的需求在实时中出现,我的应用程序需要存储如此多的数据怎么办?是否有任何配置可以更改以满足我的要求? - Lalith
即使在第一个客户端创建了所有的50000个密钥之前,如果我运行第二个客户端,它会先完成,然后才是第一个客户端。所以你说的可能不是我面临的问题。 - Lalith
3
页面大小和内存使用可以进行配置-请查看redis.conf中的注释。第二个客户端完成并不一定排除了这种情况-低内存条件和并发可能变得非常复杂,特别是涉及超时和自动重试的情况。例如,每次遇到错误时是否会重置所有先前的键? - Tom Clarkson
嗯...可能是这样!我会研究一下这个问题。因为我的应用程序预计要处理存储在Redis数据库中的许多并发会话,我不能容忍这种不确定性:(。 - Lalith

0

由于我在NodeJs中异步地进行了许多设置(键值),因此许多套接字连接是同时打开的。 NodeJs套接字写缓冲区可能会过载,GC可能会干扰节点进程。

附注:我按照Tom建议更改了Redis内存配置,但仍然表现相同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接