Redis进阶实践之十六 Redis大批量增加数据

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 原文:Redis进阶实践之十六 Redis大批量增加数据一、介绍          有时候,Redis实例需要在很短的时间内加载大量先前存在或用户生成的数据,以便尽可能快地创建数百万个键。这就是所谓的批量插入,本文档的目标是提供有关如何以尽可能快的速度向Redis提供数据的信息。
原文: Redis进阶实践之十六 Redis大批量增加数据

一、介绍

          有时候,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 10) | nc localhost 6379 > /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: 0, replies: 1000000


               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 由以下协议表示:

              *3<cr><lf>
              $3<cr><lf>
              SET<cr><lf>
              $3<cr><lf>
              key<cr><lf>
              $5<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 6379 --pipe
              All data transferred. Waiting for the last reply...
              Last reply received from server.
              errors: 0, replies: 1000



        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 6379 [-a "password"] -n 0 --pipe
             All data transferred.Waiting for the last reply...
             Last reply received from server.
             errors:0,replies:10000000


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


三、总结

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

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
15天前
|
缓存 NoSQL 关系型数据库
13- Redis和Mysql如何保证数据⼀致?
该内容讨论了保证Redis和MySQL数据一致性的几种策略。首先提到的两种方法存在不一致风险:先更新MySQL再更新Redis,或先删Redis再更新MySQL。第三种方案是通过MQ异步同步以达到最终一致性,适用于一致性要求较高的场景。项目中根据不同业务需求选择不同方案,如对一致性要求不高的情况不做处理,时效性数据设置过期时间,高一致性需求则使用MQ确保同步,最严格的情况可能涉及分布式事务(如Seata的TCC模式)。
41 6
|
15天前
|
NoSQL Redis
05- Redis的数据淘汰策略有哪些 ?
Redis 提供了 8 种数据淘汰策略:挥发性 LRU、LFU 和 TTL(针对有过期时间的数据),挥发性随机淘汰,以及全库的 LRU、LFU 随机淘汰,用于在内存不足时选择删除。另外,还有不淘汰策略(no-eviction),允许新写入操作报错而非删除数据。
194 1
|
22天前
|
NoSQL Redis
Redis事务:保证数据操作的一致性和可靠性
Redis事务:保证数据操作的一致性和可靠性
|
23小时前
|
存储 缓存 NoSQL
Redis入门到通关之Redis缓存数据实战
Redis入门到通关之Redis缓存数据实战
|
17天前
|
存储 NoSQL 算法
redis数据持久化
redis数据持久化
|
22天前
|
NoSQL 安全 网络安全
保护Redis:建立铁壁般的安全防线,守护你的数据财富
保护Redis:建立铁壁般的安全防线,守护你的数据财富
|
22天前
|
消息中间件 存储 NoSQL
Redis Stream: 实时消息处理的利器,让你的数据流畅又可靠!
Redis Stream: 实时消息处理的利器,让你的数据流畅又可靠!
|
22天前
|
NoSQL 安全 网络安全
Redis连接:加速数据访问与保障安全传输的关键
Redis连接:加速数据访问与保障安全传输的关键
|
22天前
|
存储 消息中间件 缓存
Redis 字符串:用一串数据解决多种问题
Redis 字符串:用一串数据解决多种问题
|
1月前
|
存储 JSON NoSQL
Redis与Python的完美结合:实现高效数据交互和应用场景全解析
Redis与Python的完美结合:实现高效数据交互和应用场景全解析
115 0

热门文章

最新文章