phpredis管道是否与使用协议进行大规模插入相同?
我正在将我的站点的一部分从关系数据库移动到Redis,需要在可能短的时间内插入数以百万计的密钥 在我的例子中,数据必须首先从MySQL获取,由PHP准备,然后添加到相应的排序集(时间作为分数+ID作为值)。目前我正在使用phpredis multi-method的phpredis管道是否与使用协议进行大规模插入相同?,php,insert,redis,phpredis,Php,Insert,Redis,Phpredis,我正在将我的站点的一部分从关系数据库移动到Redis,需要在可能短的时间内插入数以百万计的密钥 在我的例子中,数据必须首先从MySQL获取,由PHP准备,然后添加到相应的排序集(时间作为分数+ID作为值)。目前我正在使用phpredis multi-method的Redis::PIPELINE参数。尽管速度有了明显的提高,但在执行导入时,它还是阻止了读取并减慢了加载时间 所以问题来了——在phpredis中使用管道是否等同于中描述的质量插入 下面是一个例子: phpredis方式: 我是p
Redis::PIPELINE
参数。尽管速度有了明显的提高,但在执行导入时,它还是阻止了读取并减慢了加载时间
所以问题来了——在phpredis中使用管道是否等同于中描述的质量插入
下面是一个例子:
- phpredis方式:
Redis::PIPELINE
模式时,会发生的情况是,它不会在调用命令时发送命令,而是将其放入“待发送”命令列表中。然后,一旦调用exec()
,就会用所有命令创建一个大的命令缓冲区并发送到Redis
命令全部发送后,phpredis读取每个回复并根据每个命令规范打包结果(例如,HMGET
调用作为关联数组返回等)
phpredis中的流水线性能实际上相当好,应该足以满足几乎所有用例。也就是说,您仍然在通过PHP处理每个命令,这意味着您将通过为每个命令调用phpredis扩展本身来支付函数调用开销。此外,phpredis将花费时间处理和格式化每个回复 如果您的用例需要将大量数据导入Redis,特别是如果您不需要处理每个回复(而是只想知道所有命令都已处理),那么批量导入方法就是最好的选择 实际上,我在这里创建了一个项目: 此扩展背后的思想是,您可以使用命令调用它,然后将缓冲区保存到磁盘,磁盘将采用原始Redis协议,并与
cat buffer.txt | Redis cli--pipe
样式插入兼容
需要注意的一点是,目前不能简单地将任何给定的phpredis调用替换为对RedisMI对象的调用,因为命令被处理为变量参数调用(如hiredis),这适用于大多数但不是所有phpredis命令
下面是一个简单的示例,说明如何使用它:
<?php
$obj_mi = new RedisMI();
// Some context we can pass around in RedisMI for whatever we want
$obj_context = new StdClass();
$obj_context->session_id = "some-session-id";
// Attach this context to the RedisMI object
$obj_mi->SetInfo($obj_context);
// Set a callback when a buffer is saved
$obj_mi->SaveCallback(
function($obj_mi, $str_filename, $i_cmd_count) {
// Output our context info we attached
$obj_context = $obj_mi->GetInfo();
echo "session id: " . $obj_context->session_id . "\n";
// Output the filename and how many commands were sent
echo "buffer file: " . $str_filename . "\n";
echo "commands : " . $i_cmd_count . "\n";
}
);
// A thousand SADD commands, adding three members each time
for($i=0;$i<1000;$i++) {
$obj_mi->sadd('some-set', "$i-one", "$i-two", "$i-three");
}
// A thousand ZADD commands
for($i=0;$i<1000;$i++) {
$obj_mi->zadd('some-zset', $i, "member-$i");
}
// Save the buffer
$obj_mi->SaveBuffer('test.buf');
?>
干杯 谢谢你的回答!我设法处理了数据库中的2000万行,并使用事务在redis中存储了大约250万个密钥。然而,由于redis非常出色,并且在我们的堆栈中发挥了巨大的作用,因此在未来我一定会尝试您的解决方案。
cat data.txt | redis-cli --pipe
<?php
$obj_mi = new RedisMI();
// Some context we can pass around in RedisMI for whatever we want
$obj_context = new StdClass();
$obj_context->session_id = "some-session-id";
// Attach this context to the RedisMI object
$obj_mi->SetInfo($obj_context);
// Set a callback when a buffer is saved
$obj_mi->SaveCallback(
function($obj_mi, $str_filename, $i_cmd_count) {
// Output our context info we attached
$obj_context = $obj_mi->GetInfo();
echo "session id: " . $obj_context->session_id . "\n";
// Output the filename and how many commands were sent
echo "buffer file: " . $str_filename . "\n";
echo "commands : " . $i_cmd_count . "\n";
}
);
// A thousand SADD commands, adding three members each time
for($i=0;$i<1000;$i++) {
$obj_mi->sadd('some-set', "$i-one", "$i-two", "$i-three");
}
// A thousand ZADD commands
for($i=0;$i<1000;$i++) {
$obj_mi->zadd('some-zset', $i, "member-$i");
}
// Save the buffer
$obj_mi->SaveBuffer('test.buf');
?>
➜ tredismi php mi.php
session id: some-session-id
buffer file: test.buf
commands : 2000
➜ tredismi cat test.buf|redis-cli --pipe
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 2000