如何在Node.js中将数据管道传输到Redis?

14

我有大量数据需要插入(SET \ INCR)到Redis数据库中,因此我正在寻找通过node.js进行管道 \ 批量插入的方法。

我在node.js中没有找到任何好的示例/ API来执行此操作,所以希望能得到任何帮助!

4个回答

13

是的,我必须同意这方面缺乏示例,但我设法创建了一个流,向其中发送了多个批量插入命令。

您应该安装Redis Stream模块:

npm install redis-stream

这是使用流的方法:

var redis = require('redis-stream'),
    client = new redis(6379, '127.0.0.1');

// Open stream
var stream = client.stream();

// Example of setting 10000 records
for(var record = 0; record < 10000; record++) {

    // Command is an array of arguments:
    var command = ['set', 'key' + record, 'value'];  

    // Send command to stream, but parse it before
    stream.redis.write( redis.parse(command) );
}

// Create event when stream is closed
stream.on('close', function () {
    console.log('Completed!');

    // Here you can create stream for reading results or similar
});

// Close the stream after batch insert
stream.end();

另外,您可以创建任意数量的流,并在任何时间打开/关闭它们。

redis-stream node模块上有几个示例展示如何在node.js中使用redis流。


谢谢 Toni!你知道它是否能够与Lua脚本一起使用吗? - Aviram Netanel
1
嗯,我没有尝试过,但我认为你可以在 Redis 实例中加载脚本,并使用通过管道发送的 evalevalsha 命令来运行它们。 - Toni
我按照你的代码原样运行,但没有设置任何键。之后通过redis-cli调用“keys *”会返回一个空集合。 - Jake
@Jake 你说得对。感谢你的报告。这个已经过时了。我现在检查了 redis-stream 的新版本,命令已经改变,只有一个在这个例子中:以前是: stream.write( ... )在新版本中是: stream.redis.write( ... ) - Toni

6

谢谢!我真的尝试过使用multi和eval&exec,但性能甚至更差... - Aviram Netanel

3
你可能也需要查看batch()。使用multi()会更慢的原因是它是事务性的。如果出现错误,将不会执行任何操作。也许这正是你想要的,但在速度方面你有选择余地。
redis-stream包似乎没有使用Redis的批量插入功能,所以它比Redis网站上使用redis-cli进行大规模插入时要慢。
另一个想法是使用redis-cli并给它提供一个文件流,这个NPM包就是这样做的:https://github.com/almeida/redis-mass 不喜欢先写入磁盘文件吗?这个库:https://github.com/eugeneiiim/node-redis-pipe/blob/master/example.js也可以直接流式传输到Redis,而无需写入文件。它会向生成的进程流式传输并定期刷新缓冲区。
在Redis的网站上,在大规模插入(http://redis.io/topics/mass-insert)下,可以看到一个小的Ruby示例。上面的库基本上将其移植到了Node.js,然后直接流式传输到生成的redis-cli进程。
所以在Node.js中,我们有: var redisPipe = spawn('redis-cli', ['--pipe']); spawn()返回对子进程的引用,你可以使用stdin进行管道操作。例如:redisPipe.stdin.write()
你只需要继续写入缓冲区,将其流式传输到子进程,然后定期清除它。这样就不会填满它,因此在内存方面要比node_redis包好一些(它的文档中明确说明数据保存在内存中),尽管我没有深入研究过,所以我不知道内存占用的情况。它可能也是在做同样的事情。
当然要记住,如果出现问题,所有操作都会失败。这就是像fluentd这样的工具被创建的原因(这又是另一个选项:http://www.fluentd.org/plugins/all - 它有几个Redis插件)。但同样意味着你需要在某个地方备份数据。我个人也使用Embulk来做这个(需要一个磁盘文件),但它不支持批量插入,所以速度很慢。30,000条记录需要近2个小时。
一种流式处理方法(不依赖磁盘)的好处在于,如果你正在从另一个数据源进行大量插入操作,假设该数据源返回了大量数据,而您的服务器没有足够的硬盘空间来支持所有数据 - 您可以选择流式传输。但是,这种方法也存在失败的风险。
我自己也遇到过这种情况,我正在构建一个Docker镜像,它将在一台硬盘空间不足以容纳大型数据集的服务器上运行。当然,如果您可以将所有内容都放在服务器的硬盘上,那就轻松得多了...但是,如果不能,则流式传输到redis-cli可能是您唯一的选择。
如果您经常需要处理大量数据,我会真诚地推荐使用fluentd。它带有许多出色的功能,可以确保您的数据到达目的地,如果发生故障,它可以恢复。
所有这些Node.js方法的一个问题在于,如果出现故障,您要么失去所有数据,要么必须重新插入所有数据。

1

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