通常來講,redis主從和mysql主從目的差很少,但redis主從配置很簡單,主要在從節點配置文件指定主節點ip和端口,好比:slaveof 192.168.10.10 6379,而後啓動主從,主從就搭建好了。redis主從中若是主節點發生故障,不會自動切換,須要藉助redis的Sentinel(哨兵模式)或者keepalive來實現主的故障轉移。node
今天介紹下redis cluster集羣模式:
redis集羣是一個無中心的分佈式redis存儲架構,能夠在多個節點之間進行數據共享,解決了redis高可用、可擴展等問題,redis集羣提供瞭如下兩個好處:
1)將數據自動切分(split)到多個節點
2)當集羣中的某一個節點故障時,redis還能夠繼續處理客戶端的請求。mysql
一個 Redis 集羣包含 16384 個哈希槽(hash slot),數據庫中的每一個數據都屬於這16384個哈希槽中的一個。集羣使用公式 CRC16(key) % 16384 來計算鍵 key 屬於哪一個槽。集羣中的每個節點負責處理一部分哈希槽。
集羣中的主從複製
集羣中的每一個節點都有1個至N個複製品,其中一個爲主節點,其他的爲從節點,若是主節點下線了,集羣就會把這個主節點的一個從節點設置爲新的主節點,繼續工做。這樣集羣就不會由於一個主節點的下線而沒法正常工做。linux
==========從Redis3.x開始已經支持Load Balance功能了===========c++
Redis Cluster集羣功能推出已經有一段時間了。在單機版的Redis中,每一個Master之間是沒有任何通訊的,因此通常在Jedis客戶端或者Codis這樣的代理中作Pre-sharding。按照CAP理論來講,單機版的Redis屬於保證CP(Consistency & Partition-Tolerancy)而犧牲A(Availability),也就說Redis可以保證全部用戶看到相同的數據(一致性,由於Redis不自動冗餘數據)和網絡通訊出問題時,暫時隔離開的子系統能繼續運行(分區容忍性,由於Master之間沒有直接關係,不須要通訊),可是不保證某些結點故障時,全部請求都能被響應(可用性,某個Master結點掛了的話,那麼它上面分片的數據就沒法訪問了)。git
有了Cluster功能後,Redis從一個單純的NoSQL內存數據庫變成了分佈式NoSQL數據庫,CAP模型也從CP變成了AP。也就是說,經過自動分片和冗餘數據,Redis具備了真正的分佈式能力,某個結點掛了的話,由於數據在其餘結點上有備份,因此其餘結點頂上來就能夠繼續提供服務,保證了Availability。然而,也正由於這一點,Redis沒法保證曾經的強一致性了。這也是CAP理論要求的,三者只能取其二。redis
Redis Cluster 是Redis的集羣實現,內置數據自動分片機制,集羣內部將全部的key映射到16384個Slot中,集羣中的每一個Redis Instance負責其中的一部分的Slot的讀寫。集羣客戶端鏈接集羣中任一Redis Instance便可發送命令,當Redis Instance收到本身不負責的Slot的請求時,會將負責請求Key所在Slot的Redis Instance地址返回給客戶端,客戶端收到後自動將原請求從新發往這個地址,對外部透明。一個Key到底屬於哪一個Slot由crc16(key) % 16384 決定。在Redis Cluster裏對於負載均衡和HA相關都已經支持的至關完善了。算法
負載均衡(Load Balance):集羣的Redis Instance之間能夠遷移數據,以Slot爲單位,但不是自動的,須要外部命令觸發。
集羣成員管理:集羣的節點(Redis Instance)和節點之間兩兩按期交換集羣內節點信息而且更新,從發送節點的角度看,這些信息包括:集羣內有哪些節點,IP和PORT是什麼,節點名字是什麼,節點的狀態(好比OK,PFAIL,FAIL,後面詳述)是什麼,包括節點角色(master 或者 slave)等。
關於可用性,集羣由N組主從Redis Instance組成。spring
主能夠沒有從,可是沒有從 意味着主宕機後主負責的Slot讀寫服務不可用。sql
一個主能夠有多個從,主宕機時,某個從會被提高爲主,具體哪一個從被提高爲主,協議相似於Raft,參見這裏。如何檢測主宕機?Redis Cluster採用quorum+心跳的機制。從節點的角度看,節點會按期給其餘全部的節點發送Ping,cluster-node-timeout(可配置,秒級)時間內沒有收到對方的回覆,則單方面認爲對端節點宕機,將該節點標爲PFAIL狀態。經過節點之間交換信息收集到quorum個節點都認爲這個節點爲PFAIL,則將該節點標記爲FAIL,而且將其發送給其餘全部節點,其餘全部節點收到後當即認爲該節點宕機。從這裏能夠看出,主宕機後,至少cluster-node-timeout時間內該主所負責的Slot的讀寫服務不可用。mongodb
Redis Cluster的特色以下:
======Redis-Cluster採用無中心結構,每一個節點保存數據和整個集羣狀態,每一個節點都和其餘全部節點鏈接======
redis-cluster架構圖以下:
其結構特色:
redis cluster集羣是爲了下降單節點或單純主從redis的壓力,主主節點之間是不存在同步關係的,各主從之間的數據存在同步關係。有多少主節點,就會把16384個哈希槽(hash slot)平均分配到這些主節點上,當往redis裏寫入數據時,會根據哈希算法算出這個數的哈希槽,決定它放到哪個主節點上,而後這個主節點的從節點去自動同步。在客戶端隨便鏈接一個主節點便可,主節點之間會進行內部跳轉!當取對應數據時,各節點之間會自動跳轉到所取數據所在的主節點上!
1)redis cluster節點分配
假設現有有三個主節點分別是:A、 B、C ,它們能夠是一臺機器上的三個端口,也能夠是三臺不一樣的服務器。那麼,採用哈希槽 (hash slot)的方式
來分配16384個slot 的話,它們三個節點分別承擔的slot 區間是:
節點A 覆蓋0-5460;
節點B 覆蓋5461-10922;
節點C 覆蓋10923-16383.
獲取數據:
若是存入一個值,按照redis cluster哈希槽的算法: CRC16('key')%16384 = 6782。 那麼就會把這個key 的存儲分配到 B 上了。一樣,當我鏈接
(A,B,C)任何一個節點想獲取'key'這個key時,也會這樣的算法,而後內部跳轉到B節點上獲取數據
新增一個主節點:
新增一個節點D,redis cluster的這種作法是從各個節點的前面各拿取一部分slot到D上,我會在接下來的實踐中實驗。大體就會變成這樣:
節點A 覆蓋1365-5460
節點B 覆蓋6827-10922
節點C 覆蓋12288-16383
節點D 覆蓋0-1364,5461-6826,10923-12287
一樣刪除一個節點也是相似,移動完成後就能夠刪除這個節點了。
2)Redis Cluster主從模式
redis cluster 爲了保證數據的高可用性,加入了主從模式,一個主節點對應一個或多個從節點,主節點提供數據存取,從節點則是從主節點拉取數據
備份,當這個主節點掛掉後,就會有這個從節點選取一個來充當主節點,從而保證集羣不會掛掉。
上面那個例子裏, 集羣有A、B、C三個主節點, 若是這3個節點都沒有加入從節點,若是B掛掉了,咱們就沒法訪問整個集羣了。A和C的slot也沒法訪問。
因此在集羣創建的時候,必定要爲每一個主節點都添加了從節點, 好比像這樣, 集羣包含主節點A、B、C, 以及從節點A一、B一、C1, 那麼即便B掛掉系統也
能夠繼續正確工做。B1節點替代了B節點,因此Redis集羣將會選擇B1節點做爲新的主節點,集羣將會繼續正確地提供服務。 當B從新開啓後,它就會變成B1的從節點。
不過須要注意,若是節點B和B1同時掛了,Redis集羣就沒法繼續正確地提供服務了。
===========廢話很少說,下面記錄下搭建redis cluster集羣==========
因爲最小的redis集羣須要3個主節點(即Redis Cluster集羣至少須要3個master節點,也就是說至少須要6個節點才能構建Redis cluster集羣),一臺機器可運行多個redis實例(通常使用兩臺機器,每臺啓動3個redis實例,即三個主節點,三個從節點)。不少案例使用單臺服務器開6個端口,操做差很少,只是配置基本相對簡單點,多臺服務器更接近生產環境。【當集羣最開始建立好後,要記住各節點的主從關係(或是建立的時候指定主從關係);如果其中一臺機器重啓,重啓後,需從新將其加入到redis cluster集羣中;這就須要將這臺機器上的各節點以前的從節點變爲主節點(客戶端執行slaveof no one),而後再根據新的主節點添加這臺機器的各節點到集羣中,添加後變爲從節點】
本案例redis cluster節點信息:
redis01
172.16.51.175:7000
172.16.51.175:7001
172.16.51.175:7002
redis02
172.16.51.176:7003
172.16.51.176:7004
172.16.51.176:7005
redis03
172.16.51.178:7006
172.16.51.178:7007
172.16.51.178:7008
先說下redis01節點的部署過程(其餘兩臺節點部署過程一致)
我的運維習慣,會專門建立一個app帳號,用戶部署應用程序。本案例應用程序都部署在/data目錄下,將/data權限設置成app [root@bl-redis01 ~]# useradd app [root@bl-redis01 ~]# passwd app [root@bl-redis01 ~]# chown -R app.app /data 前提準備 1)安裝 GCC 編譯工具 否則會有編譯不過的問題 [root@bl-redis01 ~]# yum install -y gcc g++ make gcc-c++ kernel-devel automake autoconf libtool make wget tcl vim ruby rubygems unzip git 2)升級全部的包,防止出現版本太久不兼容問題 [root@bl-redis01 ~]# yum -y update 3)關閉防火牆 節點以前須要開放指定端口,爲了方便,生產不要禁用 [root@bl-redis01 ~]# /etc/init.d/iptables stop [root@bl-redis01 ~]# setenforce 0 [root@bl-redis01 ~]# vim /etc/sysconfig/selinux ...... SELINUX=disabled ...... redis cluster集羣部署 4)下載並編譯安裝redis [root@bl-redis01 ~]# su - app [app@bl-redis01 ~]$ mkdir /data/software/ [app@bl-redis01 software]$ wget http://download.redis.io/releases/redis-4.0.1.tar.gz [app@bl-redis01 software]$ tar -zvxf redis-4.0.1.tar.gz [app@bl-redis01 software]$ mv redis-4.0.1 /data/ [app@bl-redis01 software]$ cd /data/redis-4.0.1/ [app@bl-redis01 redis-4.0.1]$ make -------------------------------------------------------------------------------------- 若是由於上次編譯失敗,有殘留的文件,作法以下: [app@bl-redis01 redis-4.0.1]$ make distclean -------------------------------------------------------------------------------------- 5)建立節點 首先在172.16.51.175機器(redis01)上/data/redis-4.0.1目錄下建立redis-cluster目錄 [app@bl-redis01 redis-4.0.1]$ mkdir /data/redis-4.0.1/redis-cluster 接着在redis-cluster目錄下,建立名爲7000、700一、7002的目錄 [app@bl-redis01 redis-cluster]$ mkdir 7000 [app@bl-redis01 redis-cluster]$ mkdir 7001 [app@bl-redis01 redis-cluster]$ mkdir 7002 分別修改這三個配置文件redis.conf [app@bl-redis01 redis-4.0.1]$ cd redis-cluster/ [app@bl-redis01 redis-cluster]$ ll total 12 drwxrwxr-x 2 app app 4096 Nov 16 17:38 7000 drwxrwxr-x 2 app app 4096 Nov 16 17:39 7001 drwxrwxr-x 2 app app 4096 Nov 16 17:39 7002 [app@bl-redis01 redis-cluster]$ cat 7000/redis.conf port 7000 bind 172.16.51.175 daemonize yes pidfile /var/run/redis_7000.pid cluster-enabled yes cluster-config-file nodes_7000.conf cluster-node-timeout 10100 appendonly yes [app@bl-redis01 redis-cluster]$ cat 7001/redis.conf port 7001 bind 172.16.51.175 daemonize yes pidfile /var/run/redis_7001.pid cluster-enabled yes cluster-config-file nodes_7001.conf cluster-node-timeout 10100 appendonly yes [app@bl-redis01 redis-cluster]$ cat 7002/redis.conf port 7002 bind 172.16.51.175 daemonize yes pidfile /var/run/redis_7002.pid cluster-enabled yes cluster-config-file nodes_7002.conf cluster-node-timeout 10100 appendonly yes ---------------------------------------------------------------------------------------------------- redis.conf的配置說明: #端口7000,7001,7002 port 7000 #默認ip爲127.0.0.1,須要改成其餘節點機器可訪問的ip,不然建立集羣時沒法訪問對應的端口,沒法建立集羣 bind 172.16.51.175 #redis後臺運行 daemonize yes #pidfile文件對應7000,7001,7002 pidfile /var/run/redis_7000.pid #開啓集羣,把註釋#去掉 cluster-enabled yes #集羣的配置,配置文件首次啓動自動生成 7000,7001,7002 cluster-config-file nodes_7000.conf #請求超時,默認15秒,可自行設置 cluster-node-timeout 10100 #aof日誌開啓,有須要就開啓,它會每次寫操做都記錄一條日誌 appendonly yes ---------------------------------------------------------------------------------------------------- 接着在另外兩臺機器上(172.16.51.176,172.16.51.178)重複以上三步,只是把目錄改成700三、700四、7005和700六、700七、7008,對應的配置文件也按照這個規則修改便可(即修改redis.conf文件中的端口就好了) 6)啓動集羣(依次啓動7000-7008端口) #第一個節點機器上執行 3個節點 [app@bl-redis01 redis-cluster]$ for((i=0;i<=2;i++)); do /data/redis-4.0.1/src/redis-server /data/redis-4.0.1/redis-cluster/700$i/redis.conf; done #第二個節點機器上執行 3個節點 [app@bl-redis01 redis-cluster]$ for((i=3;i<=5;i++)); do /data/redis-4.0.1/src/redis-server /data/redis-4.0.1/redis-cluster/700$i/redis.conf; done #第三個節點機器上執行 3個節點 [app@bl-redis01 redis-cluster]$ for((i=6;i<=8;i++)); do /data/redis-4.0.1/src/redis-server /data/redis-4.0.1/redis-cluster/700$i/redis.conf; done 7)檢查服務 檢查各 Redis 各個節點啓動狀況 [app@bl-redis01 redis-cluster]$ ps -ef | grep redis app 2564 2405 0 20:13 pts/0 00:00:00 grep redis app 15197 1 0 17:57 ? 00:00:05 /data/redis-4.0.1/src/redis-server 172.16.51.175:7000 [cluster] app 15199 1 0 17:57 ? 00:00:05 /data/redis-4.0.1/src/redis-server 172.16.51.175:7001 [cluster] app 15201 1 0 17:57 ? 00:00:05 /data/redis-4.0.1/src/redis-server 172.16.51.175:7002 [cluster] [app@bl-redis01 redis-cluster]$ ps -ef | grep redis app 2566 2405 0 20:13 pts/0 00:00:00 grep redis app 15197 1 0 17:57 ? 00:00:05 /data/redis-4.0.1/src/redis-server 172.16.51.175:7000 [cluster] app 15199 1 0 17:57 ? 00:00:05 /data/redis-4.0.1/src/redis-server 172.16.51.175:7001 [cluster] app 15201 1 0 17:57 ? 00:00:05 /data/redis-4.0.1/src/redis-server 172.16.51.175:7002 [cluster] 8)安裝 Ruby(須要切換到root帳號下進行安裝,app帳號下權限不夠) [root@bl-redis01 ~]# yum -y install ruby ruby-devel rubygems rpm-build [root@bl-redis01 ~]# gem install redis ----------------------------------------------------------------------------------------------------- 注意:在centos6.x下執行上面的"gem install redis"操做可能會報錯,坑不少! 默認yum安裝的ruby版本是1.8.7,版本過低,須要升級到ruby2.2以上,不然執行上面安裝會報錯! 首先安裝rvm(或者直接下載證書:https://pan.baidu.com/s/1slTyJ7n 密鑰:7uan 下載並解壓後直接執行"curl -L get.rvm.io | bash -s stable"便可) [root@bl-redis01 ~]# curl -L get.rvm.io | bash -s stable //可能會報錯,須要安裝提示進行下面一步操做 [root@bl-redis01 ~]# curl -sSL https://rvm.io/mpapis.asc | gpg2 --import - //而後再接着執行:curl -L get.rvm.io | bash -s stable [root@bl-redis01 ~]# find / -name rvm.sh /etc/profile.d/rvm.sh [root@bl-redis01 ~]# source /etc/profile.d/rvm.sh [root@bl-redis01 ~]# rvm requirements 而後升級ruby到2.3 [root@bl-redis01 ~]# rvm install ruby 2.3.1 [root@bl-redis01 ~]# ruby -v ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux] 列出全部ruby版本 [root@bl-redis01 ~]# rvm list 設置默認的版本 [root@bl-redis01 ~]# rvm --default use 2.3.1 更新下載源 [root@bl-redis01 ~]# gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org https://gems.ruby-china.org/ added to sources source https://rubygems.org not present in cache [root@bl-redis01 ~]# gem sources *** CURRENT SOURCES *** https://rubygems.org/ https://gems.ruby-china.org/ 最後就能順利安裝了 [root@bl-redis01 src]# gem install redis Successfully installed redis-4.0.1 Parsing documentation for redis-4.0.1 Done installing documentation for redis after 1 seconds 1 gem installed ----------------------------------------------------------------------------------------------------- 9)建立集羣 千萬注意:在任意一臺上運行便可,不要在每臺機器上都運行,一臺就夠了!!!! Redis 官方提供了 redis-trib.rb 這個工具,就在解壓目錄的 src 目錄中 [root@bl-redis01 ~]# su - app [app@bl-redis01 ~]$ /data/redis-4.0.1/src/redis-trib.rb create --replicas 1 172.16.51.175:7000 172.16.51.175:7001 172.16.51.175:7002 172.16.51.176:7003 172.16.51.176:7004 172.16.51.176:7005 172.16.51.178:7006 172.16.51.178:7007 172.16.51.178:7008 出現下面信息,從下面信息能夠看出,本案例三臺服務器啓動9個實例,配置成4主5從,其中有一個是一主兩從,其餘3個都是一主一從。 >>> Creating cluster >>> Performing hash slots allocation on 9 nodes... Using 4 masters: 172.16.51.175:7000 172.16.51.176:7003 172.16.51.178:7006 172.16.51.175:7001 Adding replica 172.16.51.176:7004 to 172.16.51.175:7000 Adding replica 172.16.51.178:7007 to 172.16.51.176:7003 Adding replica 172.16.51.175:7002 to 172.16.51.178:7006 Adding replica 172.16.51.176:7005 to 172.16.51.175:7001 Adding replica 172.16.51.178:7008 to 172.16.51.175:7000 M: 7c622ac191edd40dd61d9b79b27f6f69d02a5bbf 172.16.51.175:7000 slots:0-4095 (4096 slots) master M: 44c81c15b01d992cb9ede4ad35477ec853d70723 172.16.51.175:7001 slots:12288-16383 (4096 slots) master S: 38f03c27af39723e1828eb62d1775c4b6e2c3638 172.16.51.175:7002 replicates f1abb62a8c9b448ea14db421bdfe3f1d8075189c M: 987965baf505a9aa43e50e46c76189c51a8f17ec 172.16.51.176:7003 slots:4096-8191 (4096 slots) master S: 6555292fed9c5d52fcf5b983c441aff6f96923d5 172.16.51.176:7004 replicates 7c622ac191edd40dd61d9b79b27f6f69d02a5bbf S: 2b5ba254a0405d4efde4c459867b15176f79244a 172.16.51.176:7005 replicates 44c81c15b01d992cb9ede4ad35477ec853d70723 M: f1abb62a8c9b448ea14db421bdfe3f1d8075189c 172.16.51.178:7006 slots:8192-12287 (4096 slots) master S: eb4067373d36d8a8df07951f92794e67a6aac022 172.16.51.178:7007 replicates 987965baf505a9aa43e50e46c76189c51a8f17ec S: 2919e041dd3d1daf176d6800dcd262f4e727f366 172.16.51.178:7008 replicates 7c622ac191edd40dd61d9b79b27f6f69d02a5bbf Can I set the above configuration? (type 'yes' to accept): yes 輸入 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 172.16.51.175:7000) M: 7c622ac191edd40dd61d9b79b27f6f69d02a5bbf 172.16.51.175:7000 slots:0-4095 (4096 slots) master 2 additional replica(s) S: 6555292fed9c5d52fcf5b983c441aff6f96923d5 172.16.51.176:7004 slots: (0 slots) slave replicates 7c622ac191edd40dd61d9b79b27f6f69d02a5bbf M: 44c81c15b01d992cb9ede4ad35477ec853d70723 172.16.51.175:7001 slots:12288-16383 (4096 slots) master 1 additional replica(s) S: 2919e041dd3d1daf176d6800dcd262f4e727f366 172.16.51.178:7008 slots: (0 slots) slave replicates 7c622ac191edd40dd61d9b79b27f6f69d02a5bbf M: f1abb62a8c9b448ea14db421bdfe3f1d8075189c 172.16.51.178:7006 slots:8192-12287 (4096 slots) master 1 additional replica(s) S: eb4067373d36d8a8df07951f92794e67a6aac022 172.16.51.178:7007 slots: (0 slots) slave replicates 987965baf505a9aa43e50e46c76189c51a8f17ec S: 38f03c27af39723e1828eb62d1775c4b6e2c3638 172.16.51.175:7002 slots: (0 slots) slave replicates f1abb62a8c9b448ea14db421bdfe3f1d8075189c S: 2b5ba254a0405d4efde4c459867b15176f79244a 172.16.51.176:7005 slots: (0 slots) slave replicates 44c81c15b01d992cb9ede4ad35477ec853d70723 M: 987965baf505a9aa43e50e46c76189c51a8f17ec 172.16.51.176:7003 slots:4096-8191 (4096 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. 10)關閉集羣 推薦作法: [app@bl-redis01 ~]$ pkill redis [app@bl-redis02 ~]$ pkill redis [app@bl-redis03 ~]$ pkill redis 或者循環節點逐個關閉 [app@bl-redis01 ~]$ for((i=0;i<=2;i++)); do /opt/redis-4.0.1/src/redis-cli -c -h 172.16.51.175 -p 700$i shutdown; done [app@bl-redis02 ~]$ for((i=3;i<=5;i++)); do /opt/redis-4.0.1/src/redis-cli -c -h 172.16.51.176 -p 700$i shutdown; done [app@bl-redis03 ~]$ for((i=6;i<=8;i++)); do /opt/redis-4.0.1/src/redis-cli -c -h 172.16.51.178 -p 700$i shutdown; done 11)集羣驗證 鏈接集羣測試 參數-C可鏈接到集羣,由於redis.conf將bind改成了ip地址,因此-h參數不能夠省略,-p參數爲端口號 能夠先在172.16.51.175機器redis 7000 的節點set一個key [app@bl-redis01 ~]$ /data/redis-4.0.1/src/redis-cli -h 172.16.51.175 -c -p 7000 172.16.51.175:7000> set name www.ymq.io -> Redirected to slot [5798] located at 172.16.51.176:7003 OK 172.16.51.176:7003> get name "www.ymq.io" 172.16.51.176:7003> 由上面信息可發現redis set name 以後重定向到172.16.51.176機器 redis 7003 這個節點 而後在172.16.51.178機器redis 7008 的節點get一個key [app@bl-redis03 ~]$ /data/redis-4.0.1/src/redis-cli -h 172.16.51.178 -c -p 7008 172.16.51.178:7008> get name -> Redirected to slot [5798] located at 172.16.51.176:7003 "www.ymq.io" 172.16.51.176:7003> 發現redis get name 重定向到172.16.51.176機器 redis 7003 這個節點. 若是看到這樣的現象,說明redis cluster集羣已是可用的了!!!!!! 12)檢查集羣狀態(經過下面的命令,能夠看到本案例實現的是4主5從,4個主節點會默認分配到三個機器上,每一個機器上都要有master;另:建立集羣的時候能夠指定master和slave。這裏我是默認建立的) [app@bl-redis01 ~]$ /data/redis-4.0.1/src/redis-cli -h 172.16.51.175 -c -p 7000 172.16.51.175:7000> [app@bl-redis01 ~]$ /data/redis-4.0.1/src/redis-trib.rb check 172.16.51.175:7000 >>> Performing Cluster Check (using node 172.16.51.175:7000) M: 5a43e668f53ff64da68be31afe6dc6ea1f3c14c5 172.16.51.175:7000 slots:0-4095 (4096 slots) master 2 additional replica(s) M: c64b0839e0199f73c5c192cc8c90f12c999f79b2 172.16.51.175:7001 slots:12288-16383 (4096 slots) master 1 additional replica(s) S: 81347f01cf38d8f0faef1ad02676ebb4cffbec9e 172.16.51.176:7005 slots: (0 slots) slave replicates c64b0839e0199f73c5c192cc8c90f12c999f79b2 M: da5dde3f2f02c232784bf3163f5f584b8cf046f2 172.16.51.178:7006 slots:8192-12287 (4096 slots) master 1 additional replica(s) M: b217ab2a6c05497af3b2a859c1bb6b3fae5e0d92 172.16.51.176:7003 slots:4096-8191 (4096 slots) master 1 additional replica(s) S: 0420c49fbc9f1fe16066d189265cca2f5e71c86e 172.16.51.178:7007 slots: (0 slots) slave replicates b217ab2a6c05497af3b2a859c1bb6b3fae5e0d92 S: 5ad89453fb36e50ecc4560de6b4acce1dbbb78b3 172.16.51.176:7004 slots: (0 slots) slave replicates 5a43e668f53ff64da68be31afe6dc6ea1f3c14c5 S: bbd1f279b99b95cf00ecbfab22b6b8dd5eb05989 172.16.51.178:7008 slots: (0 slots) slave replicates 5a43e668f53ff64da68be31afe6dc6ea1f3c14c5 S: e95407b83bfeb30e3cc537161eadc372d6aa1fa2 172.16.51.175:7002 slots: (0 slots) slave replicates da5dde3f2f02c232784bf3163f5f584b8cf046f2 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. 13)列出集羣節點 列出集羣當前已知的全部節點(node),以及這些節點的相關信息 [app@bl-redis01 ~]$ /data/redis-4.0.1/src/redis-cli -h 172.16.51.175 -c -p 7000 172.16.51.175:7000> cluster nodes 5a43e668f53ff64da68be31afe6dc6ea1f3c14c5 172.16.51.175:7000@17000 myself,master - 0 1510836027000 1 connected 0-4095 c64b0839e0199f73c5c192cc8c90f12c999f79b2 172.16.51.175:7001@17001 master - 0 1510836030068 2 connected 12288-16383 81347f01cf38d8f0faef1ad02676ebb4cffbec9e 172.16.51.176:7005@17005 slave c64b0839e0199f73c5c192cc8c90f12c999f79b2 0 1510836031000 6 connected da5dde3f2f02c232784bf3163f5f584b8cf046f2 172.16.51.178:7006@17006 master - 0 1510836031000 7 connected 8192-12287 b217ab2a6c05497af3b2a859c1bb6b3fae5e0d92 172.16.51.176:7003@17003 master - 0 1510836030000 4 connected 4096-8191 0420c49fbc9f1fe16066d189265cca2f5e71c86e 172.16.51.178:7007@17007 slave b217ab2a6c05497af3b2a859c1bb6b3fae5e0d92 0 1510836029067 8 connected 5ad89453fb36e50ecc4560de6b4acce1dbbb78b3 172.16.51.176:7004@17004 slave 5a43e668f53ff64da68be31afe6dc6ea1f3c14c5 0 1510836032672 5 connected bbd1f279b99b95cf00ecbfab22b6b8dd5eb05989 172.16.51.178:7008@17008 slave 5a43e668f53ff64da68be31afe6dc6ea1f3c14c5 0 1510836031000 9 connected e95407b83bfeb30e3cc537161eadc372d6aa1fa2 172.16.51.175:7002@17002 slave da5dde3f2f02c232784bf3163f5f584b8cf046f2 0 1510836031672 7 connected 14)打印集羣信息 [app@bl-redis01 ~]$ /data/redis-4.0.1/src/redis-cli -h 172.16.51.175 -c -p 7000 172.16.51.175:7000> cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:9 cluster_size:4 cluster_current_epoch:9 cluster_my_epoch:1 cluster_stats_messages_ping_sent:8627 cluster_stats_messages_pong_sent:8581 cluster_stats_messages_sent:17208 cluster_stats_messages_ping_received:8573 cluster_stats_messages_pong_received:8626 cluster_stats_messages_meet_received:8 cluster_stats_messages_received:17207 ------------------------------------------------------------------------------------------------ [root@bl-redis01 src]# pwd /data/redis-4.0.1/src [root@bl-redis01 src]# ./redis-trib.rb help Usage: redis-trib <command> <options> <arguments ...> create host1:port1 ... hostN:portN --replicas <arg> check host:port info host:port fix host:port --timeout <arg> reshard host:port --from <arg> --to <arg> --slots <arg> --yes --timeout <arg> --pipeline <arg> rebalance host:port --weight <arg> --auto-weights --use-empty-masters --timeout <arg> --simulate --pipeline <arg> --threshold <arg> add-node new_host:new_port existing_host:existing_port --slave --master-id <arg> del-node host:port node_id set-timeout host:port milliseconds call host:port command arg arg .. arg import host:port --from <arg> --copy --replace help (show this help) For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster. 上面已經屢次出現了slot這個詞,略爲解釋一下: redis-cluster把整個集羣的存儲空間劃分爲16384個slot(譯爲:插槽?),當9個實例分爲3主6從時,至關於整個cluster中有3組HA的節點, 3個master會平均分攤全部slot,每次向cluster中的key作操做時(好比:讀取/寫入緩存),redis會對key值作CRC32算法處理,獲得一個數值, 而後再對16384取模,經過餘數判斷該緩存項應該落在哪一個slot上,肯定了slot,也就肯定了保存在哪一個master節點上,當cluster擴容或刪除 節點時,只須要將slot從新分配便可(即:把部分slot從一些節點移動到其它節點)。 --------------------------------------------------------------------------------------------------------- 在代碼裏鏈接以上redis cluster集羣節點配置以下: spring.redis.cluster.nodes = 172.16.51.175:7000,172.16.51.175:7001,172.16.51.175:7002,172.16.51.176:7003,172.16.51.176:7004,172.16.51.176:7005,172.16.51.178:7006,172.16.51.178:7007,172.16.51.178:7008
==========================集羣模式配置======================
如下這種方式貌似不能按照本身的思路添加主從 redis-trib.rb create --replicas 1 192.168.1.101:6381 192.168.1.102:6382 192.168.1.103:6383 192.168.1.102:6381 192.168.1.103:6382 192.168.1.101:6383 思路改成先加主庫 再加從庫 添加主庫 redis-trib.rb create 192.168.1.101:6381 192.168.1.102:6382 192.168.1.103:6383 添加從庫 把 102的6381 做爲從庫加入 101的6381 redis-trib.rb add-node --slave 192.168.1.102:6381 192.168.1.101:6381 redis-trib.rb add-node --slave 192.168.1.103:6382 192.168.1.102:6382 redis-trib.rb add-node --slave 192.168.1.101:6383 192.168.1.103:6383 檢測 redis-trib.rb check 192.168.1.101:6381 redis-trib.rb check 192.168.1.102:6382 redis-trib.rb check 192.168.1.103:6383
==========================redis cluster常見的幾個問題======================
1)問題一 因爲redis clster集羣節點宕機(或節點的redis服務重啓),致使了部分slot數據分片丟失;在用check檢查集羣運行狀態時,遇到錯誤; [root@slave2 redis]# redis-trib.rb check 192.168.1.100:7000 ........ [ERR] Not all 16384 slots are covered by nodes. 緣由分析: 這個每每是因爲主node移除了,可是並無移除node上面的slot,從而致使了slot總數沒有達到16384,其實也就是slots分佈不正確。 因此在刪除節點的時候必定要注意刪除的是不是Master主節點。 解決辦法: 官方是推薦使用redis-trib.rb fix 來修復集羣。經過cluster nodes看到7001這個節點被幹掉了。能夠按照下面操做進行修復 [root@slave2 redis]# redis-trib.rb fix 192.168.1.100:7000 修復完成後再用check命令檢查下是否正確(查看別的節點) [root@slave2 redis]# redis-trib.rb check 192.168.1.101:7002 只要輸入任意集羣中節點便可,會自動檢查全部相關節點。 能夠查看相應的輸出看下是不是每一個Master都有了slots。 若是分佈不均勻那可使用下面的方式從新分配slot: [root@slave2 redis]# redis-trib.rb reshard 192.168.1.100:7000 特別注意: 在部分節點重啓後從新回到集羣中的過程期間,在check集羣狀態的時候會出現"[ERR] Not all 16384 slots are covered by nodes."這個報錯, 須要稍微等待一會,等重啓節點徹底回到集羣中後,這個報錯就會消失! ====================================================== 問題二: 在往redis cluster集羣環境中添加節點時遇到一個問題,提示新增的Node不爲空: [root@slave2 redis]# redis-trib.rb add-node --slave 192.168.1.103:7004 192.168.1.102:7002 ....... [ERR] Node 192.168.1.103:7004 is not empty. Either the nodealready knows other nodes (check with CLUSTER NODES) or contains some key in database 0. 解決辦法:(若是redis cluster全部節點同時斷電同時宕機, 則節點重啓後, 只能從新建立集羣, 以前的集羣數據所有丟失! 從新建立集羣前,各節點要以下操做) 1)將192.168.1.103節點機redis下的aof、rdb等本地備份文件所有刪除 2)同時將新Node的集羣配置文件刪除,也便是刪除redis.conf裏面cluster-config-file指定所在的文件; 3)"redis-cli -c -h 192.168.1.103 -p 7004"登錄後,執行 "flushdb"命令進行清除操做 4)重啓reds服務 5)最後再次執行節點添加操做 ============================================================================================= 舒適提示: - 集羣中只要有一組master-slave節點同時掛點,則集羣服務也會掛掉;待該組master和slave節點的redis恢復後,這部分slot槽的數據也會丟失。 - 集羣中1/2或master節點掛掉,則集羣服務也會掛掉;待這些master節點服務重啓後,會自動加入到集羣中,需等待一段時間,集羣恢復正常,數據不會丟失。 - 集羣中master節點關閉,須要等待一小段時間,它對應的slave節點就會變成master節點,集羣服務正常,數據會隨之到新的maser節點的slot。 - master節點掛掉後,重啓redis服務(必定要在原來的aof和nodes*.conf文件路徑下啓動),則會自動加入到cluster集羣中,並會變成slave節點。 - 新添加的master節點的slot默認爲0,master主節點若是沒有slots,存取數據就都不會被選中! 故要爲新增長的master節點進行reshard從新分配slot。 - slave從節點的slot爲0,數據不會存儲在slave節點!只會存儲在master主節點中,master節點纔有slot數值。 ====================================================== 注意:每一組的master-slave節點不能同時掛掉或短期內前後掛掉,不然這部分slot內的數據就會丟失。 好比說一主一從,當master節點掛掉後,數據都保存到slave節點內,稍過一會,slave節點就會被選舉爲新的master節點。 老的master節點重啓後從新回到集羣中,並自動變爲它原來的slave(如今是新的master)的slave節點,並自動同步數據。 這個時候新的master節點若是掛掉,則數據一樣會保存到新的slave節點中,新的slave節點過一段時間一樣會被再次選舉爲新的master,如此類推.... 若是master節點和它的slave節點同時掛掉,或者在其中一個掛掉後尚未來得及恢復到集羣中,另外一個就掛掉,這種狀況下,這部分slot槽的數據確定就沒有了。 因此說,通常會重啓一個節點,待該節點恢復到集羣中後,再能夠重啓它對應的slave或master節點。 redis做爲純緩存服務時,數據丟失,通常對業務是無感的,不影響業務,丟失後會再次寫入。但若是做爲存儲服務(即做爲存儲數據庫),數據丟失則對業務影響很大。 不過通常業務場景,存儲數據庫會用mysql、oracle或mongodb。 ====================================================== redis cluster集羣節點重啓後,要想恢復集羣狀態,正確的作法是: 1)要在各個節點原來的appendonly.aof ,dump.rdb,nodes_*.conf 文件所在路徑下重啓redis服務。這樣就能確保redis啓動後用到以前的數據文件。 (可使用find命令查找這些文件所在路徑,而後在這個路徑下啓動redis服務) 2)各個節點的redis服務正常啓動後,就能夠直接查看redis cluster狀態了,檢查集羣狀態是否恢復。 注意: 必定要在原來的數據文件的路徑下啓動redis,若是啓動的路徑錯誤,則讀取的數據文件就不是以前的了,這樣集羣就很難恢復了。這個時候就須要刪除以前的數據文件, 從新建立集羣了。(或者直接在/data/redis-4.0.6/redis-cluster/700*目錄下的redis.conf文件裏的cluster-config-file指定文件的絕對路徑) 集羣節點的redis服務重啓後,check集羣狀態,若有下面告警信息,處理以下: [root@redis-node01 redis-cluster]# /data/redis-4.0.6/src/redis-trib.rb check 192.168.1.100:7000 ........... ........... [OK] All nodes agree about slots configuration. >>> Check for open slots... [WARNING] Node 192.168.1.100:7000 has slots in importing state (5798,11479). [WARNING] Node 192.168.1.100:7001 has slots in importing state (1734,5798). [WARNING] Node 192.168.1.101:7002 has slots in importing state (11479). [WARNING] The following slots are open: 5798,11479,1734 >>> Check slots coverage... [OK] All 16384 slots covered. 解決辦法: 必定要登陸到告警信息中的節點和對應的端口上進行操做。 執行"cluster setslot <slot> stable"命令,表示取消對槽slot 的導入( import)或者遷移( migrate)。 執行後,這部分slot槽的數據就沒了。 [root@redis-node01 redis-cluster]# /data/redis-4.0.6/src/redis-cli -h 192.168.1.100 -c -p 7000 192.168.1.100:7000> cluster setslot 5798 stable OK 192.168.1.100:7000> cluster setslot 11479 stable OK [root@redis-node01 redis-cluster]# /data/redis-4.0.6/src/redis-cli -h 192.168.1.100 -c -p 7001 192.168.1.100:7001> cluster setslot 1734 stable OK 192.168.1.100:7001> cluster setslot 5798 stable OK [root@redis-node01 redis-cluster]# /data/redis-4.0.6/src/redis-cli -h 192.168.1.101 -c -p 7002 192.168.1.101:7002> cluster setslot 11479 stable OK 再次檢查redis cluster集羣狀態,就會發現一切正常了! [root@redis-node01 redis-cluster]# /data/redis-4.0.6/src/redis-trib.rb check 192.168.1.100:7000 >>> Performing Cluster Check (using node 192.168.1.100:7000) M: 39737de1c48fdbaec304f0d11294286593553365 192.168.1.100:7000 slots:0-5460 (5461 slots) master 1 additional replica(s) S: 61a0cc84069ced156b6e1459bb71cab225182385 192.168.1.101:7003 slots: (0 slots) slave replicates 39737de1c48fdbaec304f0d11294286593553365 S: 75de8c46eda03aee1afdd39de3ffd39cc42a5eec 172.16.60.209:7005 slots: (0 slots) slave replicates 70a24c750995e2f316ee15320acb73441254a7aa M: 70a24c750995e2f316ee15320acb73441254a7aa 192.168.1.101:7002 slots:5461-10922 (5462 slots) master 1 additional replica(s) S: 5272bd14768e3e32e165284c272525a7da47b47e 192.168.1.100:7001 slots: (0 slots) slave replicates c1b71d52b0d804f499c9166c0c1f4e3c35077ee9 M: c1b71d52b0d804f499c9166c0c1f4e3c35077ee9 172.16.60.209:7004 slots:10923-16383 (5461 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.