一、介绍

有时候,Redis实例需要在很短的时间内加载大量先前存在或用户生成的数据,以便尽可能快地创建数百万个键。这就是所谓的批量插入,本文档的目标是提供有关如何以尽可能快的速度向Redis提供数据的信息。如果想查看英文原文,地址如下:https://redis.io/topics/mass-insert

二、操作详解

话不多说,直接进入主题了。

          1、使用协议,卢克(Use the protocol, Luke)

使用普通Redis客户端的方式执行批量插入的操作并不是一个很好的办法,原因如下:发送一个命令的方式很慢,因为您必须为每个命令都会有往返的时间消耗。虽然可以使用管道模式来操作,但为了批量插入多条记录,您需要在读取回复的同时编写新命令,以确保尽可能快地插入。

另外,只有一小部分客户端支持非阻塞 I/O 操作,而且并不是所有的客户端都能够以最大化吞吐量这种有效的方式来解析这些回复。 由于以上这些原因,将大量数据导入Redis的首选方式是生成包含Redis协议的文本文件(原始格式),以便调用插入所需数据所需的命令。

例如,如果我需要生成一个大型数据集,其中包含数十亿个键:“keyN - > ValueN”,我将创建一个包含如下Redis协议格式的命令的文件:

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

一旦创建了该文件,剩下的操作就是尽可能快地将其提供给Redis。在过去,做法是使用如下的netcat的命令:

                (cat data.txt; sleep ) | nc localhost  > /dev/null

然而,这并不是一个非常可靠的方式来执行批量导入,因为 netcat 命令并不会真正知道所有数据何时传输完毕,并且也无法检查发生的错误。在Redis的2.6或更高版本中,redis-cli实用程序支持称为管道的新模式,该模式就是为了执行批量插入而存在的。

使用管道模式,运行的命令如下所示:

                cat data.txt | redis-cli --pipe

这将产生类似于这样的输出:

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

redis-cli实用程序还将确保只将从Redis实例收到的错误重定向到标准输出。

         2、生成Redis协议(Generating Redis Protocol)

Redis协议生成和解析非常简单,如果想了解协议的详情,英文原地址点击《这里》,我翻译的文章的地址点击《Redis进阶实践之十七 Redis协议的规范》。然而,为了生成用于大容量插入协议的目标,您不需要了解协议的每个细节,只需要按照以下方式书写每个命令:

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

其中<cr>表示“\r”(或ASCII字符13),<lf>表示“\n”(或ASCII字符10)。

例如,命令 SET key value 由以下协议表示:

              *<cr><lf>
$<cr><lf>
SET<cr><lf>
$<cr><lf>
key<cr><lf>
$<cr><lf>
value<cr><lf>

或者表示为引用的字符串:

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

为批量插入而生成的文件只不过是由以上述方式表示的一个接一个的命令组成的。

以下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}"))
}

我们可以在redis-cli的管道中直接运行程序,以执行我们的第一次海量导入会话。

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

       3、管道模式如何在引擎下工作(How the pipe mode works under the hoods)

redis-cli管道模式的速度和netcat一样快,与此同时,仍然能够明白服务器最后一次发送回复的时间。

这是通过以下方式获得的:

           3.1、redis-cli --pipe Redis客户端会尽可能快的向服务器发送数据。

                  3.2、同时,会尽可能快的读取并解析数据文件中的内容。

                  3.3、一旦从标准输入设备读取数据完毕,它将会发送一个带有20个字节的字符串的特殊的ECHO命令到服务器:我们确信这是最新发送的命令,如果我们收到作为批量回复的相同的20个字节的消息,我们确信可以做“答复匹配检查”。

                  3.4、这个特殊的最终命令一经发送,Redis服务器端将接收到回复和这20个字节的回复消息做匹配。如果匹配,它可以成功退出,表示插入完毕。

使用这个技巧,我们不需要解析我们发送给服务器的协议,以了解我们发送了多少条命令,仅仅是一个答复而已。

但是,在解析回复时,我们会对所有解析的回复进行计数,以便在最后我们能够告诉用户传输到服务器的命令的数量在这次批量插入的会话中。

4、示例代码操作

  4.1、准备数据文件,格式是文本文件,名称是:redis_commands.txt。

我在Windows环境下生成了一个txt文件,一条数据一行,代码如下:

                 SET Key0 Value0
SET Key1 Value1
SET Key2 Value2
SET Key3 Value3
SET Key4 Value4
SET Key5 Value5
SET Key6 Value6
SET Key7 Value7
SET Key8 Value8
SET Key9 Value9
SET Key10 Value10
...
SET KeyN ValueN

我生成了500万的数据,因为这个文本文件我是在Windows环境下生成的,所以需要格式转换。

          4.2、如果使用Windows环境下生成的文件,需要进行格式转换,如果是在Linux环境下生成的文件就不需要格式转换,如果文本文件比较大,执行转换时间会有几秒,等待即可。

执行格式转换

              [root@linux ~]# unix2dos redis_commands.txt
unix2dos:converting file redis_commands.txt to DOS format ...

以上代码进行格式转换完毕

需要说明一点,unix2dos这个命令需要先安装,如果没有安装,会提示:command not found。

执行以下命令安装:

              [root@linux ~]# yum install unix2dos

   4.3、进行数据批量插入

             [root@linux ~]# cat redis_commands.txt | redis-cli -h 192.168.127.130 -p  [-a "password"] -n  --pipe
All data transferred.Waiting for the last reply...
Last reply received from server.
errors:,replies:

批量插入数据成功,一千万的数据大概要花费50几秒左右。

三、总结

好的,今天就写到这里,大批量数据插入的就是这么容易。只要理解了,其实也不是很难,技术就是一层窗户纸,一捅就破,但是没人捅就比较麻烦。下一篇文章,我们将写一些关于redis协议格式的文章,如果要涉及大批量数据插入,就会涉及到redis规范协议的问题。

Redis进阶实践之十六 Redis大批量增加数据的更多相关文章

  1. Redis进阶实践之十二 Redis的Cluster集群动态扩容

    一.引言     上一篇文章我们一步一步的教大家搭建了Redis的Cluster集群环境,形成了3个主节点和3个从节点的Cluster的环境.当然,大家可以使用 Cluster info 命令查看Cl ...

  2. Redis进阶实践之十九 Redis如何使用lua脚本

    一.引言               redis学了一段时间了,基本的东西都没问题了.从今天开始讲写一些redis和lua脚本的相关的东西,lua这个脚本是一个好东西,可以运行在任何平台上,也可以嵌入 ...

  3. Redis进阶实践之十八 使用管道模式加速Redis查询

    一.引言             学习redis 也有一段时间了,该接触的也差不多了.后来有一天,以为同事问我,如何向redis中批量的增加数据,肯定是大批量的,为了这主题,我从新找起了解决方案.目前 ...

  4. Redis进阶实践之十八 使用管道模式提高Redis查询的速度

    原文:Redis进阶实践之十八 使用管道模式提高Redis查询的速度 一.引言             学习redis 也有一段时间了,该接触的也差不多了.后来有一天,以为同事问我,如何向redis中 ...

  5. Redis进阶实践之十 Redis主从复制的集群模式

    一.引言        Redis的基本数据类型,高级特性,与Lua脚本的整合等相关知识点都学完了,说是学完了,只是完成了当前的学习计划,在以后的时间还需继续深入研究和学习.从今天开始来讲一下有关Re ...

  6. Redis进阶实践之十 Redis哨兵集群模式

    一.引言             上一篇文章我们详细的讲解了Redis的主从集群模式,其实这个集群模式配置很简单,只需要在Slave的节点上进行配置,Master主节点的配置不需要做任何更改,但是有一 ...

  7. Redis进阶实践之十四 Redis-cli命令行工具使用详解第一部分

    一.介绍       redis学了有一段时间了,以前都是看视频,看教程,很少看官方的东西.现在redis的东西要看的都差不多看完了.网上的东西也不多了.剩下来就看看官网的东西吧,一遍翻译,一遍测试. ...

  8. Redis进阶实践之十五 Redis-cli命令行工具使用详解第二部分(结束)

    一.介绍           今天继续redis-cli使用的介绍,上一篇文章写了一部分,写到第9个小节,今天就来完成第二部分.话不多说,开始我们今天的讲解.如果要想看第一篇文章,地址如下:http: ...

  9. Redis进阶实践之十四 Redis-cli命令行工具使用详解

    转载来源:http://www.cnblogs.com/PatrickLiu/p/8508975.html 一.介绍 redis学了有一段时间了,以前都是看视频,看教程,很少看官方的东西.现在redi ...

随机推荐

  1. idea编译时JDK版本变化

    修改参考:http://www.cnblogs.com/woshimrf/p/5863248.html 添加maven-compiler-plugin插件.

  2. 在linux内核中实现自己的系统调用

    如实现一个简单的打印:printk 1.cd linux-ok6410/kernel/ vim printk.cvoid sys_pk(){printk("<0>this is ...

  3. 读书共享 Primer Plus C-part11

    第十四章结构和其他数据形式 关于fread以及fwrite fread(char* buff,int size,int count,FILE* fp) fwrite(char* buff,int si ...

  4. Redis 学习(一) —— 安装、通用key操作命令

    一.Redis介绍 1.介绍 通常,在系统中,我们会把数据交由数据库来存储,但传统的数据库增删查改的性能较差,且比较复杂.根据 80/20 法则,百分之八十的业务访问集中在百分之二十的数据上.是否可以 ...

  5. mac攻略(4) -- 使用brew配置php7开发环境(mac+php+apache+mysql+redis)

    [http://www.cnblogs.com/redirect/p/6131751.html] 网上有很多文章都是错误的,因为是copy别人的,作者没有自己亲测,不仅不能给新手提供帮助,还会产生严重 ...

  6. 用Python发送邮件

    文件:send.py # -*- coding:utf-8 -*- # ## 任兴测试用Python发送邮件 import os import sys import getopt import tim ...

  7. Linux 快速执行历史命令,用 !编号

    例如: history | grep mysql 使用 !914 可以快速执行上述命令:

  8. 开启MySQL远程访问权限 允许远程连接

    1.登陆mysql数据库 mysql -u root -p 查看user表 mysql> use mysql;Database changedmysql> select host,user ...

  9. Python3实现QQ机器人自动爬取百度文库的搜索结果并发送给好友(主要是爬虫)

    一.效果如下: 二.运行环境: win10系统:python3:PyCharm 三.QQ机器人用的是qqbot模块 用pip安装命令是: pip install qqbot (前提需要有request ...

  10. Java经典编程题50道之二十三

    给一个不多于5位的正整数,要求:①求它是几位数:②逆序打印出各位数字. public class Example23 {    public static void main(String[] arg ...