1. 程式人生 > >開啟運維之路之第 9 篇——Redis單機多點叢集

開啟運維之路之第 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個雜湊槽沒能正常分配。