開啟運維之路之第 9 篇——Redis單機多點叢集
Redis叢集
redis cluster是去中心化,去中介軟體的,也就是說,叢集中的每個節點都是平等的關係,都是對等的,每個節點都儲存各自的資料和整個叢集的狀態。每個節點都和其他所有節點連線,而且這些連線保持活躍,這樣就保證了我們只需要連線叢集中的任意一個節點,就可以獲取到其他節點的資料。
Redis 叢集採用一種叫做雜湊槽 (hash slot)的方式來分配。redis cluster 預設分配了 16384 個slot,當我們set一個key 時,會用CRC16演算法來取模得到所屬的slot,然後將這個key 分到雜湊槽區間的節點上,具體演算法就是:CRC16(key) % 16384。
注意的是:必須要3個以後的主節點,否則在建立叢集時會失敗。
假設現在有3個節點已經組成了叢集,分別是:A, B, C 三個節點,它們可以是一臺機器上的三個埠,也可以是三臺不同的伺服器。那麼,採用雜湊槽 (hash slot)的方式來分配16384個slot 的話,它們三個節點分別承擔的slot 區間是:
節點A覆蓋0-5460;
節點B覆蓋5461-10922;
節點C覆蓋10923-16383。
如果想新增一個節點D,redis cluster的這種做法是從各個節點的前面各拿取一部分slot到D上:
節點A覆蓋1365-5460
節點B覆蓋6827-10922
節點C覆蓋12288-16383
節點D覆蓋0-1364,5461-6826,10923-12287
同樣刪除一個節點也是類似,移動完成後就可以刪除這個節點了。
redis cluster 為了保證資料的高可用性,加入了主從模式,一個主節點對應一個或多個從節點,主節點提供資料存取,從節點則是從主節點拉取資料備份,當這個主節點掛掉後,就會有這個從節點選取一個來充當主節點,從而保證叢集不會掛掉。
所以我們在叢集建立的時候,一定要為每個主節點都添加了從節點, 比如像這樣, 叢集包含主節點A、B、C, 以及從節點A1、B1、C1, 那麼即使B掛掉系統也可以繼續正確工作。B1節點替代了B節點,所以Redis叢集將會選擇B1節點作為新的主節點,叢集將會繼續正確地提供服務。 當B重新開啟後,它就會變成B1的從節點。
不過需要注意,如果節點B和B1同時掛了,Redis叢集就無法繼續正確地提供服務了。
Redis單機多節點叢集:
1、將 叢集工具 redis-trib.rb 複製到 usr/local/bin 目錄下:注意要根據 redis 安裝的路徑進行選擇,如果根據本人的這套教程,就沒問題。
[[email protected] ~]# cd /root/redis-4.0.10/src/
[[email protected] src]# ls -a
可以看到叢集工具 redis-trib.rb。要加 -a 才能顯示。
複製到 usr/local/bin 目錄下:
[[email protected] src]# cp redis-trib.rb /usr/local/bin/
現在弄 3主3從,一共 6 個節點,就要涉及 6 個埠:7001,7002,7003,7004,7005,7006。前面 3 個我們用作主節點,後面 3 個從節點。
我們先在root目錄下新建一個redis_cluster目錄,然後該目錄下再建立6個目錄,目錄名分別是7001,7002,7003,7004,7005,7006,用來存在redis配置檔案。
[[email protected] src]# cd
[[email protected] ~]# mkdir redis_cluster
[[email protected] ~]# cd redis_cluster/
[[email protected] redis_cluster]# mkdir 7001 7002 7003 7004 7005 7006
[[email protected] redis_cluster]# ls
7001 7002 7003 7004 7005 7006
先複製一份 Redis 的配置檔案到 7001 目錄下:(輸入絕對路徑,就不用擔心當前處於什麼目錄下操作)
[[email protected] redis_cluster]# cp /root/redis-4.0.10/redis.conf /root/redis_cluster/7001/
修改 7001 目錄下的配置檔案:
[[email protected] redis_cluster]# cd 7001/
[[email protected] 7001]# vi redis.conf
修改下面幾個配置:特別注意,請別使用小鍵盤按數字,會產生衝突鍵,導致很多錯亂問題!請使用字母上方的數字鍵!
修改配置,要合理運用 i 輸入模式 和 Esc 模式,即修改一個,就Esc,這樣就方便進行下一個查詢和修改。
①埠號 port:7001,可以搜尋 /port 快速定位,n 是下一個,N是上一個匹配項
②後臺啟動:daemonize yes 可以搜尋:/daemonize
③pidfile檔案:可以搜尋 /pidfile 修改成:pidfile /var/run/redis_7001.pid
④開啟叢集:cluster-enabled yes 可以搜尋:/cluster-enabled 去掉前面的註釋 #
⑤儲存節點配置,自動建立:cluster-config-file nodes_7001.conf
⑥叢集超時時間,節點超過這個時間沒反應就斷定是宕機:cluster-node-timeout 5000
⑦儲存方式,將寫操作記錄儲存到日誌中:appendonly yes
OK,修改完,儲存,退出。:wq
把7001下的配置分別複製到7002-7006 然後對應的再修改下配置:
[[email protected] 7001]# cp /root/redis_cluster/7001/redis.conf /root/redis_cluster/7002/
[[email protected] 7001]# cp /root/redis_cluster/7001/redis.conf /root/redis_cluster/7003/
[[email protected] 7001]# cp /root/redis_cluster/7001/redis.conf /root/redis_cluster/7004/
[[email protected] 7001]# cp /root/redis_cluster/7001/redis.conf /root/redis_cluster/7005/
[[email protected] 7001]# cp /root/redis_cluster/7001/redis.conf /root/redis_cluster/7006/
這裡使用絕對路徑。有個技巧,鍵盤的方向鍵 上↑ 、下↓ 可以檢視之前敲過的命令。
然後,7002-7006這5個配置檔案都需要修改下面的資訊:(把所有 7001 的改成相對應的數字即可)
①埠號 port:從 7002 - 7006, 搜尋 /port
③pidfile檔案:從 7002 - 7006, 搜尋 /pidfile
⑤儲存節點配置,自動建立:從 7002 - 7006 搜尋 /cluster-config-file
小技巧:退回到上一個目錄。
[[email protected] 7001]# cd ..
[[email protected] redis_cluster]#
然後修改檔案:
[[email protected] redis_cluster]# vi 7002/redis.conf
[[email protected] redis_cluster]# vi 7003/redis.conf
[[email protected] redis_cluster]# vi 7004/redis.conf
[[email protected] redis_cluster]# vi 7005/redis.conf
[[email protected] redis_cluster]# vi 7006/redis.conf
然後小心修改。。。
修改完畢,啟動 6 個節點:
[[email protected] ~]# /usr/local/redis/bin/redis-server redis_cluster/7001/redis.conf
[[email protected] ~]# /usr/local/redis/bin/redis-server redis_cluster/7002/redis.conf
[[email protected] ~]# /usr/local/redis/bin/redis-server redis_cluster/7003/redis.conf
[[email protected] ~]# /usr/local/redis/bin/redis-server redis_cluster/7004/redis.conf
[[email protected] ~]# /usr/local/redis/bin/redis-server redis_cluster/7005/redis.conf
[[email protected] ~]# /usr/local/redis/bin/redis-server redis_cluster/7006/redis.conf
可以檢視 Redis 程序:[[email protected] ~]# ps -ef | grep redis
看到,埠號 6379 是預設的也啟動了,還有 7001 - 7006 埠號都啟動了 Redis。
接下來,建立叢集。
剛才我們已經把 叢集工具 redis-trib.rb 放到 usr/local/bin 目錄下了。
在使用前,需要安裝ruby,讓它們能連線:
[[email protected] ~]# yum -y install ruby ruby-devel rubygems rpm-build
作為依賴被升級:
elfutils-libelf.x86_64 0:0.170-4.el7 elfutils-libs.x86_64 0:0.170-4.el7
openssl.x86_64 1:1.0.2k-12.el7 openssl-libs.x86_64 1:1.0.2k-12.el7
rpm.x86_64 0:4.11.3-32.el7 rpm-build-libs.x86_64 0:4.11.3-32.el7
rpm-libs.x86_64 0:4.11.3-32.el7 rpm-python.x86_64 0:4.11.3-32.el7
完畢!
[[email protected] ~]# gem install redis
發現報錯:
[[email protected] ~]# gem install redis
Fetching: redis-4.0.1.gem (100%)
ERROR: Error installing redis:
redis requires Ruby version >= 2.2.2.
[[email protected] ~]#
要求 Ruby 的版本 在2.2.2以上,點選檢視解決方案
解決步驟:
①安裝RVM:
[[email protected] ~]# gpg2 --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3
稍等片刻。。。
[[email protected] ~]# curl -L get.rvm.io | bash -s stable
稍等片刻。。。。。。
[[email protected] ~]# find / -name rvm -print
/usr/local/rvm
/usr/local/rvm/src/rvm
/usr/local/rvm/src/rvm/bin/rvm
/usr/local/rvm/src/rvm/lib/rvm
/usr/local/rvm/src/rvm/scripts/rvm
/usr/local/rvm/bin/rvm
/usr/local/rvm/lib/rvm
/usr/local/rvm/scripts/rvm
[[email protected] ~]#
②檢視rvm庫中已知的ruby版本:
[[email protected] ~]# source /usr/local/rvm/scripts/rvm
[[email protected] ~]# rvm list known
稍等片刻。。。
③安裝一個ruby版本:
[[email protected] ~]# rvm install 2.3.3
稍等片刻。。
④使用一個ruby版本:
[[email protected] ~]# rvm use 2.3.3
Using /usr/local/rvm/gems/ruby-2.3.3
[[email protected] ~]#
⑤設定預設版本:
[[email protected] ~]# rvm use 2.3.3 --default
Using /usr/local/rvm/gems/ruby-2.3.3
[[email protected] ~]#
⑥解除安裝一個已知版本
[[email protected] ~]# rvm remove 2.0.0
ruby-2.0.0-p648 - #already gone
Using /usr/local/rvm/gems/ruby-2.3.3
⑦安裝redis:
[[email protected] ~]# gem install redis
Fetching: redis-4.0.1.gem (100%)
Successfully installed redis-4.0.1
Parsing documentation for redis-4.0.1
Installing ri documentation for redis-4.0.1
Done installing documentation for redis after 1 seconds
1 gem installed
搞定 Ruby 工具!
建立叢集:
[[email protected] ~]# redis-trib.rb create --replicas 1 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006
彈出提示,是否使用預設的主、從配置
輸入:yes
16384 個雜湊槽都被使用,說明叢集建立成功了。
有些時候,奇葩的問題如截圖:
那是因為建立叢集的時候,產生一些額外資料檔案,沒有清理掉。7001上不是空的,有資料,建立叢集會失敗。因為之前測試的資料存在這裡。因此要把它們都刪掉。步驟如下:
①檢視 redis 程序,殺掉:[[email protected] ~]# ps -ef|grep redis
說明:你們的程序跟我的不一樣,而且每次啟動之後的程序也會不一樣,以實際為準。
殺掉程序:kill -9 程序ID
[[email protected] ~]# kill -9 2385
[[email protected] ~]# kill -9 2390
[[email protected] ~]# kill -9 2395
[[email protected] ~]# kill -9 2400
[[email protected] ~]# kill -9 2407
[[email protected] ~]# kill -9 2414
[[email protected] ~]# ps -ef | grep redis
root 2446 2293 0 10:26 pts/0 00:00:00 grep --color=auto redis
[[email protected] ~]#
②進入 redis 的根目錄,把兩個檔案 anaconda-ks.cfg(未必有這個檔案,有則刪,無則不管)、appendonly.aof (aof是隱藏檔案,需要加 -a) 刪除:
[[email protected] ~]# cd /usr/local/redis/
[[email protected] redis]# ls -a
. .. appendonly.aof auth bin dump.rdb redis.conf
[[email protected] redis]# rm -rf appendonly.aof
[[email protected] redis]#
然後返回根目錄,把anaconda-ks.cfg、appendonly.aof也刪掉,以絕後患:
[[email protected] redis]# cd
[[email protected] ~]# ls
anaconda-ks.cfg nodes-7006.conf
appendonly.aof redis-4.0.10
這樣會不行,還會報錯。原因是因為:之前我們測試的時候,有錯誤的資訊,也儲存到了nodes-7001.conf檔案了。所以,我們需要把這些檔案都刪掉,還有aof等檔案。剛才說的那些檔案都刪掉。所以,正確的做法是:刪掉 aof ,6個.conf 檔案
[[email protected] ~]# rm -rf appendonly.aof
[[email protected] ~]# rm -rf anaconda-ks.cfg
[[email protected] ~]# rm -rf nodes-7001.conf
[[email protected] ~]# rm -rf nodes-7002.conf
[[email protected] ~]# rm -rf nodes-7003.conf
[[email protected] ~]# rm -rf nodes-7004.conf
[[email protected] ~]# rm -rf nodes-7005.conf
[[email protected] ~]# rm -rf nodes-7006.conf
OK,重新啟動 6 個節點,再開啟叢集即可。請先 cd 回到根目錄,再敲下面的命令:
[[email protected] ~]# /usr/local/redis/bin/redis-server redis_cluster/7001/redis.conf
[[email protected] ~]# /usr/local/redis/bin/redis-server redis_cluster/7002/redis.conf
[[email protected] ~]# /usr/local/redis/bin/redis-server redis_cluster/7003/redis.conf
[[email protected] ~]# /usr/local/redis/bin/redis-server redis_cluster/7004/redis.conf
[[email protected] ~]# /usr/local/redis/bin/redis-server redis_cluster/7005/redis.conf
[[email protected] ~]# /usr/local/redis/bin/redis-server redis_cluster/7006/redis.conf
建立叢集:
[[email protected] ~]# redis-trib.rb create --replicas 1 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006
OK,繞了一圈,很多問題會遇到,各種刪掉檔案啊、啟動啊,搞個 shell 指令碼,一鍵搞定,如何?好の!
建立 shell 命令:[[email protected] ~]# vi startRedisCluster.sh
rm -rf appendonly.aof
rm -rf anaconda-ks.cfg
rm -rf nodes-7001.conf
rm -rf nodes-7002.conf
rm -rf nodes-7003.conf
rm -rf nodes-7004.conf
rm -rf nodes-7005.conf
rm -rf nodes-7006.conf
/usr/local/redis/bin/redis-server redis_cluster/7001/redis.conf
/usr/local/redis/bin/redis-server redis_cluster/7002/redis.conf
/usr/local/redis/bin/redis-server redis_cluster/7003/redis.conf
/usr/local/redis/bin/redis-server redis_cluster/7004/redis.conf
/usr/local/redis/bin/redis-server redis_cluster/7005/redis.conf
/usr/local/redis/bin/redis-server redis_cluster/7006/redis.conf
redis-trib.rb create --replicas 1 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006
複製貼上上面的命令,輸入 i 進入編輯模式,shift + Insert 貼上。然後儲存退出。:wq
然後給 shell 指令碼授權:[[email protected] ~]# chmod u+x *.sh
OK,我們測試一下這個 shell 指令碼是否合格。先檢視 redis 程序,殺掉程序。說明,shell 指令碼沒有殺掉 redis程序,因為程序ID每次都是變動的,需要手動殺掉。還有一點,不能誤殺 Redis 程序,會導致連線中斷:
啟動我們寫的 shell 指令碼:[[email protected] ~]# ./startRedisCluster.sh
OK,沒毛病!老鐵!
叢集資料測試:
redis-cli是redis預設的客戶端工具,啟動時加上`-c`引數,`-p`指定埠,就可以連線到叢集。
[[email protected] ~]# /usr/local/redis/bin/redis-cli -c -p 7003
127.0.0.1:7003> set username biandan
OK
OK,用其它節點檢視這條資料。
127.0.0.1:7003> exit
[[email protected] ~]# /usr/local/redis/bin/redis-cli -c -p 7006
127.0.0.1:7006> get username
-> Redirected to slot [14315] located at 127.0.0.1:7003
"biandan"
看到一行:-> Redirected to slot [14315] located at 127.0.0.1:7003
直接去到 7003 的 14315 雜湊槽訪問 username 了。
說明叢集沒毛病。
接下來,測試叢集宕機!
①幹掉一個節點,比如干掉 7004:
先檢視程序:
127.0.0.1:7003> exit
[[email protected] ~]# ps -ef | grep redis
root 2297 1 0 10:58 ? 00:00:06 ./bin/redis-server *:6379
root 2527 1 0 12:12 ? 00:00:01 /usr/local/redis/bin/redis-server 127.0.0.1:7001 [cluster]
root 2532 1 0 12:12 ? 00:00:01 /usr/local/redis/bin/redis-server 127.0.0.1:7002 [cluster]
root 2537 1 0 12:13 ? 00:00:01 /usr/local/redis/bin/redis-server 127.0.0.1:7003 [cluster]
root 2542 1 0 12:13 ? 00:00:01 /usr/local/redis/bin/redis-server 127.0.0.1:7004 [cluster]
root 2547 1 0 12:13 ? 00:00:01 /usr/local/redis/bin/redis-server 127.0.0.1:7005 [cluster]
root 2552 1 0 12:13 ? 00:00:01 /usr/local/redis/bin/redis-server 127.0.0.1:7006 [cluster]
root 7463 2214 0 12:41 pts/0 00:00:00 grep --color=auto redis
[[email protected] ~]#
看到 7004 的啟動佔用 ID 為2542,幹掉它:
[[email protected] ~]# kill -9 2542
再檢視程序,確認被幹掉了:
[[email protected] ~]# ps -ef | grep redis
root 2297 1 0 10:58 ? 00:00:06 ./bin/redis-server *:6379
root 2527 1 0 12:12 ? 00:00:01 /usr/local/redis/bin/redis-server 127.0.0.1:7001 [cluster]
root 2532 1 0 12:12 ? 00:00:01 /usr/local/redis/bin/redis-server 127.0.0.1:7002 [cluster]
root 2537 1 0 12:13 ? 00:00:01 /usr/local/redis/bin/redis-server 127.0.0.1:7003 [cluster]
root 2547 1 0 12:13 ? 00:00:01 /usr/local/redis/bin/redis-server 127.0.0.1:7005 [cluster]
root 2552 1 0 12:13 ? 00:00:01 /usr/local/redis/bin/redis-server 127.0.0.1:7006 [cluster]
root 7467 2214 0 12:42 pts/0 00:00:00 grep --color=auto redis
[[email protected] ~]#
檢視叢集情況:
[[email protected] ~]# redis-trib.rb check 127.0.0.1:7001
看到,7001,7002,7003還在主節點,7005,7006是從節點。叢集還正常。
再幹掉 7002。因為 7001 VS 7004,7002 VS 7005,7003 VS 7006,它們是主從關係。
[[email protected] ~]# kill -9 2532
檢視程序:
[[email protected] ~]# ps -ef | grep redis
root 2297 1 0 10:58 ? 00:00:07 ./bin/redis-server *:6379
root 2527 1 0 12:12 ? 00:00:02 /usr/local/redis/bin/redis-server 127.0.0.1:7001 [cluster]
root 2537 1 0 12:13 ? 00:00:02 /usr/local/redis/bin/redis-server 127.0.0.1:7003 [cluster]
root 2547 1 0 12:13 ? 00:00:02 /usr/local/redis/bin/redis-server 127.0.0.1:7005 [cluster]
root 2552 1 0 12:13 ? 00:00:02 /usr/local/redis/bin/redis-server 127.0.0.1:7006 [cluster]
root 7495 2214 0 12:48 pts/0 00:00:00 grep --color=auto redis
[[email protected] ~]#
再檢視叢集情況:[[email protected] ~]# redis-trib.rb check 127.0.0.1:7001
叢集就使用不了了。16384個雜湊槽沒能正常分配。