2017-10-28 132 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,以根据您的价值数据大小查看最佳效果。