您的位置 首页 php

redis 插入大量数据(php和ruby脚本)

redis需要插入大量数据可以采取两种模式:

1.nc(netcat) 服务器ip地址 端口号 > /dev/null

2.管道(redis-cli –pipe)

第一种模式需要将生产比如10亿条数据的语句放到data.txt文件中,格式如下:

 SET Key0 Value0
SET Key1 Value1
...
SET KeyN ValueN   

最后执行:(cat data.txt;sleep 10) | nc localhost 6379 > /dev/null

但是nc并不会报错,所以我们不知道某个set命令是否有问题

第二种模式:redis版本>=2.6.0

 cat data.txt | redis-cli --pipe  

该命令会返回如下输出:

 All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 1000000  

其中errors是错误命令的数量,replies是回复的总数

以上是通过生成.txt文件进行大数据插入。

官方文档还可以通过redis protocol(协议来插入),具体可以参照appendonly.aof文件的格式,如果对redis持久化策略有研究的话就能很容易的看到aof的语法:

 *<args><cr><lf>
$<len><cr><lf>
<arg0><cr><lf>
<arg1><cr><lf>
...
<argN><cr><lf>  

直接上ruby代码:

 def gen_redis_proto(*cmd)
    proto = ""
    proto << "*"+cmd.length.to_s+"\r\n"
    cmd.each{|arg|
        proto << "$"+arg.to_s.bytesize.to_s+"\r\n"
        proto << arg.to_s+"\r\n"
    }
    proto
end

puts gen_redis_proto("SET","mykey","Hello World!").inspect  
 (0...1000).each{|n|
    STDOUT.write(gen_redis_proto("SET","Key#{n}","Value#{n}"))
}  

以上函数作用很简单,其实就是生成一下这种格式的字符串:

 "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n"  

最后执行该.rb文件:

 $ ruby proto.rb | redis-cli --pipe
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 1000  

直接上php代码:

 <?php
class GenRedisProto
{
  public function gen_redis_proto()
  {
    $arg_nums = func_num_args();
    $proto = ""; 
    $proto .= "*".$arg_nums."\r\n";
    // 获取参数具体值
    $args = func_get_args();
    foreach ($args as $key => $value) {
      $proto .= "$".strlen($value)."\r\n";
      $proto .= $value."\r\n";
    }   
    return $proto;
  }
}

$object = new GenRedisProto();
$range = range(1, 1000);
$txt = ""; 
foreach ($range as $key => $value) {
  $txt .= $object->gen_redis_proto("SET", "Key".$value, "Value".$value);
}
echo $txt;  

最后执行该.php 文件:

 $ php redis-test.php | redis-cli --pipe
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 1000  

结果是一样的,都往redis服务器生成了{key1:value1,key2:value2…,key1000:value1000}1000个key。

重要说明:使用管道发送命令时,服务器将被迫回复一个队列答复,占用很多内存。所以,如果你需要发送大量的命令,最好是把他们按照合理数量分批次的处理,例如10K的命令,读回复,然后再发送另一个10k的命令,等等。这样速度几乎是相同的,但是在回复这10k命令队列需要非常大量的内存用来组织返回数据内容。

pipe mode工作原理:难点是保证redis-cli在pipe mode模式下执行和netcat一样快的同时,如何能理解服务器发送的最后一个回复。

这是通过以下方式获得:

  • redis-cli –pipe尽可能快的把数据发送到服务器
  • 读取数据的同时并解析它。
  • 一旦没有更多的数据输入,它就会发送一个特殊的 ECHO 命令,后面跟着20个随机的字符。我们相信可以通过匹配回复相同的20个字符是同一个命令的行为。
  • 一旦这个特殊命令发出,收到的答复就开始匹配这20个字符,当匹配时,就可以成功退出了。

同时,在分析回复的时候,我们会采用计数器的方法计数,以便在最后能够告诉我们大量插入数据的数据量,也就是replies和errors。

文章来源:智云一二三科技

文章标题:redis 插入大量数据(php和ruby脚本)

文章地址:https://www.zhihuclub.com/152475.shtml

关于作者: 智云科技

热门文章

网站地图