如何高效地向Redis插入大量的數據

来源:http://www.cnblogs.com/ivictor/archive/2016/04/29/5446503.html
-Advertisement-
Play Games

最近有個哥們在群里問,有一個日誌,裡面存的是IP地址(一行一個),如何將這些IP快速導入到Redis中。 我剛開始的建議是Shell+redis客戶端。 今天,查看Redis官檔,發現文檔的首頁部分(http://www.redis.io/documentation)有一個專門的主題是講述“Redi ...


最近有個哥們在群里問,有一個日誌,裡面存的是IP地址(一行一個),如何將這些IP快速導入到Redis中。

我剛開始的建議是Shell+redis客戶端。

今天,查看Redis官檔,發現文檔的首頁部分(http://www.redis.io/documentation)有一個專門的主題是講述“Redis Mass Insertion”的,才知道自己的建議很low。

官方給出的理由如下:

Using a normal Redis client to perform mass insertion is not a good idea for a few reasons: the naive approach of sending one command after the other is slow because you have to pay for the round trip time for every command. It is possible to use pipelining, but for mass insertion of many records you need to write new commands while you read replies at the same time to make sure you are inserting as fast as possible.

Only a small percentage of clients support non-blocking I/O, and not all the clients are able to parse the replies in an efficient way in order to maximize throughput. For all this reasons the preferred way to mass import data into Redis is to generate a text file containing the Redis protocol, in raw format, in order to call the commands needed to insert the required data.

大意是:

1> 每個redis客戶端命令之間有往返時延。

2> 只要一部分客戶端支持非阻塞I/O。

個人理解是,redis命令從執行到結果返回,有一定的時延,即便採用多個redis客戶單併發插入,也很難提高吞吐量,因為,只有非阻塞I/O只能針對有限個連接操作。

 

那麼如何高效的插入呢?

官方在2.6版本推出了一個新的功能-pipe mode,即將支持Redis協議的文本文件直接通過pipe導入到服務端。

說來拗口,具體實現步驟如下:

1. 新建一個文本文件,包含redis命令

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

如果有了原始數據,其實構造這個文件並不難,譬如shell,python都可以

2. 將這些命令轉化成Redis Protocol。

因為Redis管道功能支持的是Redis Protocol,而不是直接的Redis命令。

如何轉化,可參考後面的腳本。

3. 利用管道插入

cat data.txt | redis-cli --pipe

 

Shell VS Redis pipe

下麵通過測試來具體看看Shell批量導入和Redis pipe之間的效率。

測試思路:分別通過shell腳本和Redis pipe向資料庫中插入10萬相同數據,查看各自所花費的時間。

 

Shell

腳本如下:

#!/bin/bash
for ((i=0;i<100000;i++))
do
echo -en "helloworld" | redis-cli -x set name$i >>redis.log
done

每次插入的值都是helloworld,但鍵不同,name0,name1...name99999。

 

Redis pipe

Redis pipe會稍微麻煩一點

1> 首先構造redis命令的文本文件

在這裡,我選用了python

#!/usr/bin/python
for i in range(100000):
    print 'set name'+str(i),'helloworld'

# python 1.py > redis_commands.txt

# head -2 redis_commands.txt 

set name0 helloworld
set name1 helloworld

2> 將這些命令轉化成Redis Protocol

在這裡,我利用了github上一個shell腳本,

#!/bin/bash

while read CMD; do
  # each command begins with *{number arguments in command}\r\n
  XS=($CMD); printf "*${#XS[@]}\r\n"
  # for each argument, we append ${length}\r\n{argument}\r\n
  for X in $CMD; do printf "\$${#X}\r\n$X\r\n"; done
done < redis_commands.txt

# sh 20.sh > redis_data.txt

# head -7 redis_data.txt 

*3
$3
set
$5
name0
$10
helloworld

至此,數據構造完畢。

 

測試結果

如下:

時間消耗完全不是一個量級的。

 

最後,來看看pipe的實現原理,

  • redis-cli --pipe tries to send data as fast as possible to the server.
  • At the same time it reads data when available, trying to parse it.
  • Once there is no more data to read from stdin, it sends a special ECHO command with a random 20 bytes string: we are sure this is the latest command sent, and we are sure we can match the reply checking if we receive the same 20 bytes as a bulk reply.
  • Once this special final command is sent, the code receiving replies starts to match replies with this 20 bytes. When the matching reply is reached it can exit with success.

即它會儘可能快的將數據發送到Redis服務端,並儘可能快的讀取並解析數據文件中的內容,一旦數據文件中的內容讀取完了,它會發送一個帶有20個位元組的字元串的echo命令,Redis服務端即根據此命令來確認數據已插入完畢。

 

總結:

後續有童鞋好奇,構造redis命令的時間和將命令轉化為protocol的時間,這裡一併貼下:

[root@mysql-server1 ~]# time python 1.py > redis_commands.txt

real    0m0.110s
user    0m0.070s
sys    0m0.040s
[root@mysql-server1 ~]# time sh 20.sh > redis_data.txt

real    0m7.112s
user    0m5.861s
sys    0m1.255s

 

參考文檔:

1. http://www.redis.io/topics/mass-insert

2. https://gist.github.com/abtrout/432ce44fa77a9620c739

3. http://blog.chinaunix.net/uid-26284395-id-3124337.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.Socket 幾個常用的名詞 IPC—>Inter Process Communication,進程間通信 socket —> 套接字 TCP—>Transmission Control Protocol傳輸控制協議, 什麼是Socket Socket:又稱作是套接字,網路上的兩個程式通過一個雙 ...
  • Web和Native的交互,也就是iOS object-C與Javascript之間的交互;核心代碼是 [webView stringByEvaluatingJavaScriptFromString:@"xxxxxxxxxx"]; 這裡主要用到的就是iOS WebKit載入網路頁面,功能有獲取用戶位 ...
  • 控制項屬性: android屬性 Android功能強大,界面華麗,但是眾多的佈局屬性就害苦了開發者,下麵這篇文章結合了網上不少資料, 第一類:屬性值為true或falseandroid:layout_centerHrizontal 水平居中 (Hrizontal表示水平)android:layout ...
  • 在很多地方都有人提到MySQL這個數據,之前沒有接觸過的mysql資料庫的童鞋們可以跟我一起走進mysql的世界。 http://hovertree.com/menu/mysql/ 安裝我就不多說了,都是傻瓜的安裝。 安裝好了之後就可以看到服務里多了個服務。 當然要啟動它。 根據自己的需要設置成自動 ...
  • 很多人習慣用ORACLE的DBCA工具創建、刪除資料庫,這裡總結一下手工刪除資料庫實驗的步驟,文中大量參考了樂沙彌的手動刪除ORACLE資料庫這篇博客的內容,當然還有Oracle官方相關文檔。此處實驗環境為Oracle Linux Server release 5.7,資料庫版本為10.2.0.5.... ...
  • 文章講述了對於數據量較少的處理。包括新建資料庫、使用SQL語言建表、向資料庫中導入數據、簡單的數據查詢操作等。下麵介紹一個相對上一個較為複雜的資料庫。其實也就是數據量增大了點,數據處理要求多了些,運用基礎的資料庫知識以及網上的各種講解都可以掌握這些處理方法。 例2 下麵列舉某寶一些數據處理。 Tab ...
  • 半同步複製是在主從同步複製的基礎之上,主從同步前面我的博文有介紹 Semisynchronous Replication(半同步複製)則一定程度上保證提交的事務已經傳給了至少一個備庫 MySQL在載入並開啟Semi-sync插件後,每一個提交的事務需等待至少一個備庫接收日誌後才返回給客戶端。如果做的 ...
  • 介紹 本章主要介紹怎樣對比資料庫的表結構的差異,這裡主要介紹使用mysqldiff工具來對比表結構的差異,其實在5.6版本之後通過查詢information庫中的系統表也能對比出來,但是mysqldiff還有一個好處就是可以直接生產差異的SQL語句這個功能就是我們需要利用的,而通過分析系統表要實現這 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...