redis快速的插入大量的數據

如何在服務啓動的時候快速插入大量的  過億的key value數據呢?


使用新的方式 : LUKE
以下爲幾種可能的方式:
     1、逐條命令發送,命令的傳輸時間RTT很長,速度會比較慢
     2、使用pipelining,這種方式在實現了異步IO的客戶端程序中是可行,但是隻有很少很少的客戶端代碼支持,比如php-redis的擴展就不支持異步,你必須
等待處理的返回再進行下一步操作,如果你希望異步的執行這麼辦呢?
     3、redis提供了一個新的協議,只需要你在文件中寫入以下(可以被redis解析的,遵循redis規定的luke協議的字符串),一次性發送到客戶端就可以實現。
SET Key0 Value0
SET Key1 Value1
...
SET KeyN ValueN
發送這個文件的命令在shell中你可以使用 netcat ,下面是一個demo
(cat data.txt; sleep 10) | nc localhost 6379 > /dev/null
使用上一個命令你不知道什麼時候redis的服務接受完了文件,你無法檢查錯誤,因爲它不會返回任何值,在reids2.6以後的版本中提供了 redis-pipe來專門處理大量數據插入的問題。
你可以執行下面這個命令:
cat data.txt | redis-cli --pipe
它會返回以下信息:
 
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 1000000



那麼redis的協議規範究竟要怎麼寫呢。
生成一個大量數據插入的協議其實並沒有那麼複雜,只需要按照下面文件的格式來寫就可以實現。
*<args><cr><lf>
$<len><cr><lf>
<arg0><cr><lf>
<arg1><cr><lf>
...
<argN><cr><lf>

 <cr> 就是\r   ;  <lf>就是\n,所以  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寫的一個格式轉換腳本。(github上面有腳本可以下載)
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


那麼這種工作模式爲什麼會比逐條發送命令和使用pipeling更加快速呢,下面是它的工作原理:

1、redis-cli會盡量快速的讀取並解析文件發送到服務端
2、當讀取完畢以後,客戶端通過echo命令打印一個隨機的字符串(20字節)
3、等待服務端返回應答結果,如果服務端返回的應答結果與發送的這個20個字節的字符串匹配的話就說明文件已經發送成功了。

這個方式不需要我們去了解這個協議,不需要我們瞭解發送過程,我們只需要收到返回就表示已經執行成功了。
當然如果客戶端需要知道具體執行了多少條命令,我們就需要解析返回的字符串來告訴用戶了。








發佈了32 篇原創文章 · 獲贊 7 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章