在大數據的浪潮下,redis隻提供主從分布模式越來越顯得捉襟見肘了。2015年3月底,Redis-Cluster終於出了正式版本,真可謂千呼萬喚始出來啊。下麵我們就來看看如何一步一步安裝和配置Redis集群。
全文共分9個安裝步驟進行介紹,提供了所有安裝相關的自動化腳本源碼,這些腳本可以通過配置文件擴展到多台機器多個實例的redis-cluster安裝。 操作係統:Centos6.4 Redis版本: 3.0 機器(64位):3台機器用於安裝redis集群+1台機器做總控 網路環境: 4台機器在同一個局域網 集群拓撲結構:9個實例,3主6從,每個主2個從節點。 1. 首先到redis官網下載redis3.0版本, 程序文件包居然隻有1.3MB,讚一個。
wget http://download.redis.io/releases/redis-3.0.0.tar.gz
2. 準備可執行程序:在總控機器上解壓&編譯
tar xzvf redis-3.0.0.tar.gz
cd redis-3.0.0
make
這個時候在src目錄下已經生成了redis的可執行程序了(綠色部分)
3. 準備redis的配置文件: 這裏根據:http://redis.io/topics/cluster-tutorial寫了個最簡單版本的(文件名redis.conf):
port 30000
daemonize yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly no
loglevel warning
logfile ../logs/redis.log
pidfile ../logs/redis.pid
timeout 60
tcp-keepalive 60
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir ../logs/
save 900 1
save 300 10
save 60 100000
maxclients 65536
slave-read-only yes
4. 打包程序和配置文件:使用如下的腳本,打包之後方便拷貝到三台待安裝機器上部署(文件名tar_redis.sh).
#!/bin/bash
#打包redis程序和配置
if [ $# -ne 0 ]
then
echo "Usage: $0"
exit 1
fi
rm -rf redis-server.tar.gz
mkdir -p redis-server
mkdir -p redis-server/conf
mkdir -p redis-server/sbin
mkdir -p redis-server/logs
cp -f ./redis.conf redis-server/conf/
cd ./redis-3.0.0/src/
cp -f mkreleasehdr.sh redis-benchmark redis-check-aof redis-check-dump redis-cli \
redis-sentinel redis-server redis-trib.rb ../../redis-server/sbin/
cd -
tar czvf redis-server.tar.gz redis-server
exit 0
sh tar_redis.sh執行後生成程序和配置文件包redis-server.tar.gz
5. 分發程序和配置文件包到3台待安裝安裝的機器, 這裏我們也寫了個自動腳本dist_redis.sh. (使用這個腳本需要先安裝sshpass做遠程自動登錄[見另一篇博文Linux自動密碼登陸利器sshpass中的安裝和問題說明], sshpass是建立信任關係之外的另一種選擇).該腳本的功能是:
- 刪除就的備份目錄並備份當前目錄
- 拷貝程序包到製定目錄 並 解壓
- 設置配置文件中的端口
- 執行方法: sh dist_redis.sh ipportlist.txt
#!/bin/bash
if [ $# -ne 1 ]
then
echo "Usage: $0 iplistFile"
exit 1
fi
#自動分發redis程序和配置到所有機器[見輸入的iplistFile]
username='root'
password='123456'
dist_dir=/home/redis/redis-server/
exe_files="./redis-server.tar.gz"
echo ${dist_dir}
echo ${exe_files}
while read ipport
do
ip=`echo ${ipport} |cut -d: -f1`
port=`echo ${ipport} | cut -d: -f2`
curr_dir="`echo ${dist_dir}|sed 's:/$::g'`-${port}"
bak_dir=`echo "${curr_dir}" | sed 's:/$::g'`_bak
echo "process host:${ip}:${port} at ${curr_dir}============================================="
echo "step 1: rm old bak:${bak_dir}------------------------------------------"
sshpass -p ${password} ssh ${username}@${ip} "rm -rf ${bak_dir} 0</dev/null" 0</dev/null
echo $?
echo "step 2: backup data-------------------------------------"
sshpass -p ${password} ssh ${username}@${ip} "mv -f ${curr_dir} ${bak_dir} 2>/dev/null 1>&2 0</dev/null" 0</dev/null
echo $?
echo "step 3: mkdir dir:${curr_dir}---------------------------"
sshpass -p ${password} ssh ${username}@${ip} "mkdir -p ${curr_dir} 0</dev/null" 0</dev/null
echo $?
echo "step 4: copy tarfiles------------------------------------"
sshpass -p ${password} scp ${exe_files} ${username}@${ip}:${curr_dir}
echo $?
echo "step 5: decompress files---------------------------------"
sshpass -p ${password} ssh ${username}@${ip} "cd ${curr_dir} && tar xzvf ${exe_files} 1>/dev/null && mv -f redis-server/* . && rm -rf redis-server 0</dev/null" 0</dev/null
echo $?
echo "step 6.${i}: update conf port ---------------------------------"
sshpass -p ${password} ssh ${username}@${ip} "cd ${curr_dir} && sed -i 's/^port[ 0-9]\+$/port ${port}/g' ${curr_dir}/conf/redis.conf 0</dev/null" 0</dev/null
echo $?
done < $1
exit 0
這個腳本的輸入 ipportlist.txt文件格式為:
10.71.48.113:12000
10.71.48.114:12001
10.71.48.115:12002
10.71.48.114:12003
10.71.48.113:12004
10.71.48.115:12005
10.71.48.115:12006
10.71.48.113:12007
10.71.48.114:12008
6. 在啟動集群之前,我們需要關閉待安裝機器的防火牆。由於redis集群每個實例會開一個服務偵聽端口和一個集群內通信端口,為了方便我們這裏簡單處理,直接寫了個腳本把防火牆關閉了。也可以去iptables上配置好開放相應的端口。開關防火牆的腳本:
-
執行方法:
cat iplist.txt | sh firewall_control.sh start
#!/bin/bash
if [ $# -ne 1 ]
then
echo "Usage: $0 start|stop < iplistFile"
exit 1
fi
username='root'
password='123456'
while read ip
do
echo "at ${ip}"
if [ "${1}X" == "startX" ]
then
sshpass -p ${password} ssh ${username}@${ip} "service iptables start 0</dev/null" 0</dev/null
elif [ "${1}X" == "stopX" ]
then
sshpass -p ${password} ssh ${username}@${ip} "service iptables stop 0</dev/null" 0</dev/null
else
echo "invalid command!"
fi
done
echo "done."
exit 0
iplist.txt文件格式為:
10.71.48.113
10.71.48.114
10.71.48.115
7. 開啟redis程序: 遍曆所有實例的目錄,cd到sbin下使用./redis-server -c ../conf/redis.conf啟動redis實例, 批處理腳本redis_control.sh如下,包括了redis的開啟/關閉/重啟/存活檢測。
- 啟動: sh redis_control.sh ipportlist.txt start
- 關閉: sh redis_control.sh ipportlist.txt stop
#!/bin/bash
if [ $# -ne 2 ]
then
echo "Usage: $0 iplistFile start|stop|restart|check"
exit 1
fi
#啟動所有redis實例
username='root'
password='123456'
dist_dir=/home/redis/redis-server
exe_dir="./redis-server"
echo ${dist_dir}
command=$2
while read ipport
do
ip=`echo ${ipport} |cut -d: -f1`
port=`echo ${ipport} | cut -d: -f2`
curr_dir="`echo ${dist_dir}|sed 's:/$::g'`-${port}"
bak_dir=`echo "${curr_dir}" | sed 's:/$::g'`_bak
echo "process host:${ip}:${port} at ${curr_dir}:${command}============================================="
if [ "${command}X" == "startX" ]
then
sshpass -p ${password} ssh ${username}@${ip} "cd ${curr_dir}/sbin && ./redis-server ../conf/redis.conf" 0</dev/null
elif [ "${command}X" == "stopX" ]
then
sshpass -p ${password} ssh ${username}@${ip} "cd ${curr_dir} && cat ./logs/redis.pid |xargs kill -9" 0</dev/null
elif [ "${command}X" == "restartX" ]
then
sshpass -p ${password} ssh ${username}@${ip} "cd ${curr_dir} && cat ./logs/redis.pid |xargs kill -9" 0</dev/null
sshpass -p ${password} ssh ${username}@${ip} "cd ${curr_dir}/sbin && ./redis-server ../conf/redis.conf" 0</dev/null
elif [ "${command}X" == "checkX" ]
then
sshpass -p ${password} ssh ${username}@${ip} "ps -ef |grep redis|grep ${port}|grep -v grep" 0</dev/null
else
echo "invalid command!"
fi
echo $?
done < $1
exit 0
8. 執行上麵的start命令之後,隻是啟動了所有的實例,這些實例還沒有互相連接起來組成集群。下麵我們來看看如果把這些機器連接成集群。實際上redis官方提供了ruby腳本: ./redis-3.0.0/src/redis-trib.rb,來方便我們創建redis集群,不過需要安裝相關的工具:
-
安裝ruby:
yum install -y ruby
-
安裝rubygems:
yum install -y rubygems
, 不然會報錯: `require’: no such file to load — rubygems (LoadError) -
gem默認的源比較慢,我們刪除默認的源並添加一個源:
gem sources -r http://rubygems.org/ gem sources -a http://ruby.taobao.org/
- 安裝ruby-redis: gem install redis, 不然會報錯:in `gem_original_require’: no such file to load — redis (LoadError)
9. 安裝好上述相關工具後就可以直接使用腳本redis-trib.rb安裝了。同樣,這裏我們也對redis-trib.rb做了簡單的封裝,方便對參數的控製。封裝之後的安裝腳本為: redis_cluster_create.sh
- 執行: sh redis_cluster_create.sh ipportlist.txt
- 安裝中根據提示輸入yes即可
- 注意: –replicas 2表示每個主節點兩個從節點
#!/bin/bash
if [ $# -ne 1 ]
then
echo "Usage: $0 ipportlist.txt"
exit 1
fi
#創建集群
all_addr=""
rb="./redis-3.0.0/src/redis-trib.rb"
all_addr=`xargs -n9 < $1`
echo ${all_addr}
echo "create cluster..."
${rb} create --replicas 2 ${all_addr}
echo "done."
exit 0
執行結果:
[root@xx106 redis-install]# sh redis_cluster_create.sh ipportlist.txt
10.71.48.113:12000 10.71.48.114:12001 10.71.48.115:12002 10.71.48.114:12003 10.71.48.113:12004 10.71.48.115:12005 10.71.48.115:12006 10.71.48.113:12007 10.71.48.114:12008
create cluster...
>>> Creating cluster
Connecting to node 10.71.48.113:12000: OK
Connecting to node 10.71.48.114:12001: OK
Connecting to node 10.71.48.115:12002: OK
Connecting to node 10.71.48.114:12003: OK
Connecting to node 10.71.48.113:12004: OK
Connecting to node 10.71.48.115:12005: OK
Connecting to node 10.71.48.115:12006: OK
Connecting to node 10.71.48.113:12007: OK
Connecting to node 10.71.48.114:12008: OK
>>> Performing hash slots allocation on 9 nodes...
Using 3 masters:
10.71.48.115:12002
10.71.48.114:12001
10.71.48.113:12000
Adding replica 10.71.48.114:12003 to 10.71.48.115:12002
Adding replica 10.71.48.113:12004 to 10.71.48.115:12002
Adding replica 10.71.48.115:12005 to 10.71.48.114:12001
Adding replica 10.71.48.115:12006 to 10.71.48.114:12001
Adding replica 10.71.48.114:12008 to 10.71.48.113:12000
Adding replica 10.71.48.113:12007 to 10.71.48.113:12000
M: 3bf182ba239438d96ef6ea4f3fa1a9b333d273d7 10.71.48.113:12000
slots:10923-16383 (5461 slots) master
M: 29569c90e2d11722f676bc8c650167ec6e6fcbe1 10.71.48.114:12001
slots:5461-10922 (5462 slots) master
M: bb9b7580b7b37b11ed1218af6e3c13794756a3f3 10.71.48.115:12002
slots:0-5460 (5461 slots) master
S: ae8baf40cf3741f9d4b6f3e880ba984867f1e66b 10.71.48.114:12003
replicates bb9b7580b7b37b11ed1218af6e3c13794756a3f3
S: 32962c506aa2e1a61c15b644a1750f0685739d7b 10.71.48.113:12004
replicates bb9b7580b7b37b11ed1218af6e3c13794756a3f3
S: 7ce9a69167e3c882db81539c6f01eb3de43b1526 10.71.48.115:12005
replicates 29569c90e2d11722f676bc8c650167ec6e6fcbe1
S: 3c949cb159bc2e74f49ccf1398ea6e3279d48656 10.71.48.115:12006
replicates 29569c90e2d11722f676bc8c650167ec6e6fcbe1
S: f6e15fad28fe15e4546cb984f226c7540388e698 10.71.48.113:12007
replicates 3bf182ba239438d96ef6ea4f3fa1a9b333d273d7
S: 6b3dc056e05e06ad5fb186881a2ad201a5ba8bb0 10.71.48.114:12008
replicates 3bf182ba239438d96ef6ea4f3fa1a9b333d273d7
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join..
>>> Performing Cluster Check (using node 10.71.48.113:12000)
M: 3bf182ba239438d96ef6ea4f3fa1a9b333d273d7 10.71.48.113:12000
slots:10923-16383 (5461 slots) master
M: 29569c90e2d11722f676bc8c650167ec6e6fcbe1 10.71.48.114:12001
slots:5461-10922 (5462 slots) master
M: bb9b7580b7b37b11ed1218af6e3c13794756a3f3 10.71.48.115:12002
slots:0-5460 (5461 slots) master
M: ae8baf40cf3741f9d4b6f3e880ba984867f1e66b 10.71.48.114:12003
slots: (0 slots) master
replicates bb9b7580b7b37b11ed1218af6e3c13794756a3f3
M: 32962c506aa2e1a61c15b644a1750f0685739d7b 10.71.48.113:12004
slots: (0 slots) master
replicates bb9b7580b7b37b11ed1218af6e3c13794756a3f3
M: 7ce9a69167e3c882db81539c6f01eb3de43b1526 10.71.48.115:12005
slots: (0 slots) master
replicates 29569c90e2d11722f676bc8c650167ec6e6fcbe1
M: 3c949cb159bc2e74f49ccf1398ea6e3279d48656 10.71.48.115:12006
slots: (0 slots) master
replicates 29569c90e2d11722f676bc8c650167ec6e6fcbe1
M: f6e15fad28fe15e4546cb984f226c7540388e698 10.71.48.113:12007
slots: (0 slots) master
replicates 3bf182ba239438d96ef6ea4f3fa1a9b333d273d7
M: 6b3dc056e05e06ad5fb186881a2ad201a5ba8bb0 10.71.48.114:12008
slots: (0 slots) master
replicates 3bf182ba239438d96ef6ea4f3fa1a9b333d273d7
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
done.
10. 運行:
[root@xx113 redis-server-12004]# ./sbin/redis-cli -c -p 12004
127.0.0.1:12004> set fuqingchuan abc
-> Redirected to slot [11708] located at 10.71.48.113:12000
OK
10.71.48.113:12000> set hello world
-> Redirected to slot [866] located at 10.71.48.115:12002
OK
10.71.48.115:12002>