2017-10-28 152 views
4

我在bash腳本下面寫了處理redis鍵和值的腳本。我的Redis中有大約45-50萬個密鑰。我想檢索所有的值並做一些處理。要做到這一點,我的下面的腳本需要1個小時來處理1百萬個密鑰。爲了處理5千萬個密鑰,需要50個小時,我不想這樣做。我是redis cli的新手 - 有人可以幫助我優化下面的腳本,或者如果有人能提供一些建議,那將會非常棒。如何優化redis cli腳本來處理50百萬個密鑰

我Redis的鍵值模式:

Keys - 123.item.media 
Values - 93839,abc,98,829 | 38282,yiw,282,282 | 8922,dux,382,993 | 

Keys - 234.item.media 
Values - 2122,eww,92,211 | 8332,uei,902,872 | 9039,uns,892,782 | 

Keys - 839.item.media 
Values - 7822,nkp,77,002 | 7821,mko,999,822 | 

在下面的腳本,我通過我的所有鍵和計算,我是多麼的記錄有每個按鍵。例如 - 這個鍵(123.item.media)有3個記錄,這個(839.item.media)有兩個記錄。

所以對於波夫鍵和值,輸出應該是: 總數:8

同樣的方式,我做的所有50個百萬鍵 - 這是花費過多時間。

我的代碼:

#!/bin/sh 
cursor=-1 
keys="" 
recordCount=0 
while [ $cursor -ne 0 ]; 
do 
     if [ $cursor -eq -1 ] 
     then 
     cursor=0 
    fi 
    reply=`redis-cli SCAN $cursor MATCH "*" COUNT 100` 
    #echo $reply 
    cursor=`expr "$reply" : '\([0-9]*[0-9 ]\)'` 
    keys=${reply#[0-9]*[[:space:]]} 
    for i in $keys 
    do 
    #echo $i 
    #echo $keys 
    value=$(redis-cli GET $i) 
    temCount=`echo $value | awk -F\| '{print NF}'` 
    #echo $temCount 
    recordCount=`expr ${temCount} + ${recordCount}` 
    done 
done 

echo "Total Count: " $recordCount 

感謝您的幫助提前!

+0

請考慮以另一種語言進行此操作,因爲您正在爲每個命令創建新的進程和連接 - 嘗試C,C++,Python,Perl,PHP或其他語言。 –

回答

2

您在循環中分叉了太多次,即使對於像Bash buildins可以完成的算術這樣簡單的事情也是如此。當你在循環運行數百萬次時發生這樣的事情時,它會減慢速度。例如:

  • cursor=$(expr "$reply" : '\([0-9]*[0-9 ]\)')
  • temCount=$(echo $value | awk -F\| '{print NF}')
  • recordCount=$(expr ${temCount} + ${recordCount})

我不是一個Redis的專家。根據我的Redis-CLI的粗略的瞭解,你可以這樣做:

redis-cli --scan | sort -u > all.keys 
while read -r key; 
    value=$(redis-cli get "$key") 
    # do your processing 
done < all.keys 

如果不加快速度,接下來的想法是all.keys文件分割成幾千行的數據塊,並運行並行循環爲每個鍵的子集。如果運行速度不夠快,我推薦使用mget命令並更改循環,以便我們可以批量檢索值而不是逐個檢索。

此外,Bash可能不是這方面的最佳選擇。我相信有更好的方法可以在Python或Ruby中執行此操作。

1

很多您的時間越來越浪費了5000萬個網絡電話5000萬個鍵按這條線:

value=$(redis-cli GET $i) 

要做到批量查詢,你可以追加在列表中的GET命令的發言權1000,並使用--pipe選項進行批量查詢。質量插入

--pipe    Transfer raw Redis protocol from stdin to server. 
    --pipe-timeout <n> In --pipe mode, abort with error if after sending all data. 
        no reply is received within <n> seconds. 

例子說明here在Redis的官方文件,你可以得到類似的路線批量讀取。

這一定會給你所需的提升,並將你的腳本轉換爲幾個小時而不是50個小時。您可以將批量清單的值調整爲1000,10000或100000,以根據您的價值數據大小查看最佳效果。