分享

Redis 3.0中文官方文档翻译计划(11) ——集中插入

旧收音机 发表于 2015-4-18 20:14:53 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 0 12737
本帖最后由 旧收音机 于 2015-4-25 17:43 编辑
问题导读
1、怎么使用协议进行集中差异?
2、怎么使用生成Redis协议?
3、管道模式如何工作?





有时候Redis实例需要在短时间内加载大量的已存在数据,或者用户产生的数据,这样,上百万的键将在很短的时间内被创建。
    这被称为集中插入(mass insertion),这篇文档的目的,就是提供如何最快地向Redis中插入数据的一些相关信息。

    使用协议,伙计
    使用标准的Redis客户端来完成集中插入并不是一个好主意,理由是:一条一条的发送命令很慢,因为你需要为每个命令付出往返时间的花费。可以使用管道 (pipelining),但对于许多记录的集中插入而言,你在读取响应的同时还需要写新命令,以确保插入尽可能快。
    只有少部分的客户端支持非阻塞I/O,也并不是所有的客户端都能高效地解析响应以最大化吞吐量。基于上述这些原因,首选的集中导入数据到Redis中的方式,是生成按照Redis协议的原始(raw)格式的文本文件,以调用需要的命令来插入需要的数据。
    例如,如果我需要生成一个巨大的数据集,拥有数十亿形式为”keyN->ValueN”的键,我将创建一个按照Redis协议格式,包含如下命令的文件:
  1. SET Key0 Value0
  2. SET Key1 Value1
  3. ...
  4. SET KeyN ValueN
复制代码
当这个文件被创建后,剩下的工作就是将其尽可能快的导入到Redis中。过去的办法是使用netcat来完成,命令如下:
  1. (cat data.txt; sleep 10) | nc localhost 6379 > /dev/null
复制代码
然而,这种集中导入的方式并不是十分可靠,因为netcat并不知道所有的数据什么时候被传输完,并且不能检查错误。在github上一个不稳定的Redis分支上,redis-cli工具支持一种称为管道模式(pipe mode)的模式,设计用来执行集中插入。
    使用管道模式运行命令如下:
  1. cat data.txt | redis-cli --pipe
复制代码
输出类似如下的内容:
  1. All data transferred. Waiting for the last reply...
  2. Last reply received from server.
  3. errors: 0, replies: 1000000
复制代码
redis-cli工具也能够确保仅仅将来自Redis实例的错误重定向到标准输出。

    生成Redis协议(Generating Redis Protocol)
    Redis协议非常容易生成和解析,可以参考其文档(请关注后续翻译文档,译者注)。但是,为了集中插入的目标而生成协议,你不必了解协议的每一个细节,仅仅需要知道每个命令通过如下方式来表示:
  1. *<args><cr><lf>
  2. [        DISCUZ_CODE_248        ]lt;len><cr><lf>
  3. <arg0><cr><lf>
  4. <arg1><cr><lf>
  5. ...
  6. <argN><cr><lf>
复制代码
<cr>表示"\r" (或ASCII字符13),<lf>表示"\n" (或者ASCII字符10)。
    例如,命令SET key value通过以下协议来表示:
  1. *3<cr><lf>
  2. $3<cr><lf>
  3. SET<cr><lf>
  4. $3<cr><lf>
  5. key<cr><lf>
  6. $5<cr><lf>
  7. value<cr><lf>
复制代码
或者表示为一个字符串:
  1. "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n"
复制代码
为集中插入而生成的文件,就是由一条一条按照上面的方式表示的命令组成的。
下面的Ruby函数生成合法的协议。
  1. def gen_redis_proto(*cmd)
  2. proto = ""
  3.         proto << "*"+cmd.length.to_s+"\r\n"
  4.         cmd.each{|arg|
  5.             proto << "[        DISCUZ_CODE_7        ]quot;+arg.to_s.bytesize.to_s+"\r\n"
  6.             proto << arg.to_s+"\r\n"
  7.         }
  8.         proto
  9. end
  10. puts gen_redis_proto("SET","mykey","Hello World!").inspect
复制代码
  使用上面的函数,可以很容易地生成上面例子中的键值对。程序如下:
  1. (0...1000).each{|n|
  2. STDOUT.write(gen_redis_proto("SET","Key#{n}","Value#{n}"))
  3. }
复制代码
我们现在可以直接以redis-cli的管道模式来运行这个程序,来执行我们的第一次集中导入会话。
  1. $ ruby proto.rb | redis-cli --pipe
  2. All data transferred. Waiting for the last reply...
  3. Last reply received from server.
  4. errors: 0, replies: 1000
复制代码
管道模式如何工作(How works)
    redis-cli管道模式的魔力,就是和netcat一样的快,并且能理解服务器同时返回的最后一条响应。
    按照以下方式获得:
  • redis-cli –pipe尝试尽可能快的发送数据到服务器。
  • 与此同时读取可用数据,并尝试解析。
  • 当标准输入没有数据可读时,发送一个带有20字节随机字符的特殊ECHO命令:我们确保这是最后发送的命令,我们也确保可以匹配响应的检查,如果我们收到了相同的20字节的批量回复(bulk reply)。
  • 一旦这个特殊的最后命令被发送,收到响应的代码开始使用这20个字节来匹配响应。当匹配响应到达后成功退出。

    使用这个技巧,我们不需要为了知道发送了多少命令而解析发送给服务端的协议,仅仅只需要知道响应就可以。
    但是,在解析响应的时候,我们对所有已解析响应进行了计数,于是最后我们可以告诉用户,通过集中插入会话传输给服务器的命令的数。


相关内容:
            Redis 3.0官方文档翻译计划(1)  ——Redis介绍

             Redis 3.0官方文档翻译计划(2) ——从入门到精通(上)

             Redis 3.0官方文档翻译计划(3) ——从入门到精通(中)

            Redis 3.0官方文档翻译计划(4) ——从入门到精通(下)

           Redis 3.0中文官方文档翻译计划(5) ——使用Redis实现Twitter(上)

            Redis 3.0中文官方文档翻译计划(6) ——使用Redis实现Twitter(下)

          Redis 3.0中文官方文档翻译计划(7) ——使用Redis作为LRU缓存

            Redis 3.0中文官方文档翻译计划(8) ——分片

           Redis 3.0中文官方文档翻译计划(9) ——复制

          Redis 3.0中文官方文档翻译计划(10) ——持久化

          Redis 3.0中文官方文档翻译计划(11) ——集中插入

           Redis 3.0中文官方文档翻译计划(12) ——高可用(上)

          Redis 3.0中文官方文档翻译计划(13) ——高可用(下)

          Redis 3.0中文官方文档翻译计划(14) ——高可用客户端指引

          Redis 3.0中文官方文档翻译计划(15) ——集群(上)
          Redis 3.0中文官方文档翻译计划(16) ——集群(中)

          Redis 3.0中文官方文档翻译计划(17) ——集群(下)





















没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条