Redis:大量插入

有一些Redis实例需要在很短的时间内加载大量的的已经存在的或者用户产生的数据,因此数以百万计的键将被尽可能快的创建。

这被称为大量插入,这篇文档的目标是如何尽可能快的给Reis提供数据。

使用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并不是实时的知道什么时候所有的数据被传输完,并且不能检查错误。在Redis2.6或以后的版本中,redis-cli实用程序支持一个被称为pip mode的新模式,它就是执行大量插入而设计的。

实用管道模式运行命令看起来像下面这样:

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实例接收到的错误重定向到标准输出。

生成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 --pipe
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 1000

管道模式在后台如何运行

redis-cli管道模式的魔力之处在于,需要像netcat一样快,并同时能够理解服务器发送的最后一条回复。

使用下面的方式获得:

  • redis-cli --pipe尝试尽可能快的将数据发送给服务器。
  • 同时,当数据可用时它会读取数据,并尝试解析它
  • 一旦stdin没有数据可以读取时,它发送一个特别的ECHO命令和一个20字节的随机字符串:我们确认这是发送的最后一条命令,并且我们确认如果我们收到相同的20字节作为批量回复,我们可以匹配回复检查。
  • 一旦发送这个特殊的最终命令,接收回复的代码开始使用这20个字节匹配回复。当匹配的回复到达时,它可以成功的退出。

使用这个窍门,我们不需要解析我们发送到服务器的网关,为了理解我们发送了多少命令,

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容