1、Redis Cluster的架構(gòu)圖。

架構(gòu)細節(jié)
(1)所有的redis節(jié)點彼此互聯(lián)(PING-PONG機制),內(nèi)部使用二進制協(xié)議優(yōu)化傳輸速度和帶寬.
(2)節(jié)點的fail是通過集群中超過半數(shù)的節(jié)點檢測失效時才生效.
(3)客戶端與redis節(jié)點直連,不需要中間proxy層.客戶端不需要連接集群所有節(jié)點,連接集群中任何一個可用節(jié)點即可
(4)redis-cluster把所有的物理節(jié)點映射到[0-16383]slot上,cluster 負責維護node<->slot<->value
redis--cluster

(1)領(lǐng)著選舉過程是集群中所有master參與,如果半數(shù)以上master節(jié)點與master節(jié)點通信超過(cluster-node-timeout),認為當前master節(jié)點掛掉.
(2):什么時候整個集群不可用(cluster_state:fail),當集群不可用時,所有對集群的操作做都不可用,收到((error) CLUSTERDOWN The cluster is down)錯誤
a:如果集群任意master掛掉,且當前master沒有slave.集群進入fail狀態(tài),也可以理解成進群的slot映射[0-16383]不完成時進入fail狀態(tài).
b:如果進群超過半數(shù)以上master掛掉,無論是否有slave集群進入fail狀態(tài).
ps:當集群不可用時,所有對集群的操作做都不可用,收到((error)CLUSTERDOWN Thecluster is down)錯誤。
redis主從和MySQL主從目的差不多,但redis主從配置很簡單,主要在從節(jié)點配置文件指定主節(jié)點ip和端口:slaveof 120.77.213.193 6379,然后啟動主從,主從就搭建好了redis主從中如果主節(jié)點發(fā)生故障,不會自動切換,需要借助redis的Sentinel或者keepalive來實現(xiàn)主的故障轉(zhuǎn)移
但是搭建集群時候已經(jīng)設(shè)置過主從啦。
總結(jié):
redis集群是一個無中心的分布式redis存儲[架構(gòu)],可以在多個節(jié)點之間進行數(shù)據(jù)共享,解決了redis高可用、可擴展等問題
redis cluster在設(shè)計的時候,就考慮到了去中心化,去中間件,也就是說,集群中的每個節(jié)點都是平等的關(guān)系,都是對等的,每個節(jié)點都保存各自的數(shù)據(jù)和整個集群的狀態(tài)。每個節(jié)點都和其他所有節(jié)點連接,而且這些連接保持活躍,這樣就保證了我們只需要連接集群中的任意一個節(jié)點,就可以獲取到其他節(jié)點的數(shù)據(jù)。
redis集群提供了以下兩個好處
(1)將數(shù)據(jù)自動切分(split)到多個節(jié)點
(2)Redis 集群沒有并使用傳統(tǒng)的一致性哈希來分配數(shù)據(jù),而是采用另外一種叫做哈希槽 (hash slot)的方式來分配的。redis cluster 默認分配了 16384 個slot,當我們set一個key 時,會用CRC16算法來取模得到所屬的slot,然后將這個key 分到哈希槽區(qū)間的節(jié)點上,具體算法就是:CRC16(key) % 16384。所以我們在測試的時候看到set 和 get 的時候,直接跳轉(zhuǎn)到了7002端口的節(jié)點。
Redis 集群會把數(shù)據(jù)存在一個 master 節(jié)點,然后在這個 master 和其對應(yīng)的salve 之間進行數(shù)據(jù)同步。當讀取數(shù)據(jù)時,也根據(jù)一致性哈希算法到對應(yīng)的 master 節(jié)點獲取數(shù)據(jù)。只有當一個master 掛掉之后,才會啟動一個對應(yīng)的 salve 節(jié)點,充當 master 。
需要注意的是:必須要3個或以上的主節(jié)點,否則在創(chuàng)建集群時會失敗,并且當存活的主節(jié)點數(shù)小于總節(jié)點數(shù)的一半時,整個集群就無法提供服務(wù)了。
二、集群的使用
這表示集群中的 16384 個槽都有至少一個主節(jié)點在處理, 集群運作正常。
slots:0-5460 (5461 slots) master
slots:5461-10922 (5462 slots) master
slots:10923-16383 (5461 slots) master
集群
cluster info :打印集群的信息
cluster nodes :列出集群當前已知的所有節(jié)點( node),以及這些節(jié)點的相關(guān)信息。
節(jié)點
cluster meet <ip> <port> :將 ip 和 port 所指定的節(jié)點添加到集群當中,讓它成為集群的一份子。
cluster forget <node_id> :從集群中移除 node_id 指定的節(jié)點。
cluster replicate <node_id> :將當前節(jié)點設(shè)置為 node_id 指定的節(jié)點的從節(jié)點。
cluster saveconfig :將節(jié)點的配置文件保存到硬盤里面。
槽(slot)
cluster addslots <slot> [slot ...] :將一個或多個槽( slot)指派( assign)給當前節(jié)點。
cluster delslots <slot> [slot ...] :移除一個或多個槽對當前節(jié)點的指派。
cluster flushslots :移除指派給當前節(jié)點的所有槽,讓當前節(jié)點變成一個沒有指派任何槽的節(jié)點。
cluster setslot <slot> node <node_id> :將槽 slot 指派給 node_id 指定的節(jié)點,如果槽已經(jīng)指派給另一個節(jié)點,那么先讓另一個節(jié)點刪除該槽>,然后再進行指派。
cluster setslot <slot> migrating <node_id> :將本節(jié)點的槽 slot 遷移到 node_id 指定的節(jié)點中。
cluster setslot <slot> importing <node_id> :從 node_id 指定的節(jié)點中導(dǎo)入槽 slot 到本節(jié)點。
cluster setslot <slot> stable :取消對槽 slot 的導(dǎo)入( import)或者遷移( migrate)。
鍵
cluster keyslot <key> :計算鍵 key 應(yīng)該被放置在哪個槽上。
cluster countkeysinslot <slot> :返回槽 slot 目前包含的鍵值對數(shù)量。
cluster getkeysinslot <slot> <count> :返回 count 個 slot 槽中的鍵
增加一個主節(jié)點
redis-trib.rb add-node 127.0.0.1:7007 127.0.0.1:7001
PS:最后面這個IP:PORT可以是集群里邊兒任意一個主節(jié)點的IP和端口,下同
增加從節(jié)點
redis-trib.rb add-node --slave 127.0.0.1:7006 127.0.0.1:7000
此處的命令和添加一個主節(jié)點命令類似,此處并沒有指定添加的這個從節(jié)點的主節(jié)點,這種情況下系統(tǒng)會在其他的復(fù)制集中的主節(jié)點中隨機選取一個作為這個從節(jié)點的主節(jié)點。
指定主節(jié)點:
redis-trib.rb add-node --slave --master-id 36d53c7f1896838249c0b4afdcf680bac2f4ec2e 127.0.0.1:7008 127.0.0.1:7001
增加的節(jié)點都是空槽,若增加的是從節(jié)點
例如,要給主節(jié)點 127.0.0.1:7003添加一個從節(jié)點,該節(jié)點哈希槽的范圍1423-16383, 節(jié)點 ID 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e,我們需要鏈接新的節(jié)點(已經(jīng)是空的主節(jié)點)并執(zhí)行命令:
redis 127.0.0.1:7006> cluster replicate 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e
重新分片
所謂重新分片,就是重新分配各個節(jié)點擁有的slots,這里我們的主要目的是從老的節(jié)點中遷移一部分slots放到新節(jié)點中去,以便讓新節(jié)點真正成為集群中的一員.同樣, 還是利用redis-trib.rb 工具.
redis-trib.rb reshard 127.0.0.1:7001
//PS: 這條命令是交互的,按照提示操作即可.
[OK] All 16384 slots covered.
How many slots do you want to move (from 1 to 16384)?4096 //輸入一個數(shù),這個4096表示遷移多少個slots數(shù)
What is the receiving node ID? 36d53c7f1896838249c0b4afdcf680bac2f4ec2e //輸入目標節(jié)點ID,表示遷移到哪個目標節(jié)點
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node #1:all //輸入all表示從老的所有節(jié)點進行重分配,湊夠4096個slots給到新節(jié)點.
也可以輸入源節(jié)點id, 可以輸入多個源節(jié)點id,最后輸入done.就開始從你輸入的源節(jié)點id的節(jié)點進行遷移了
當然也可以采用非交互自動的進行遷移, 如:
[root@localhost redis-3.2.0]# /usr/local/redis/bin/redis-trib.rb reshard --from a2eee0ea546f2c3701b08981737c07938039857c --to 36d53c7f1896838249c0b4afdcf680bac2f4ec2e --slots 45 --yes 127.0.0.1:7001
--from a2eee0ea546f2c3701b08981737c07938039857c //表示從哪個節(jié)點進行遷移,即源節(jié)點
--to 36d53c7f1896838249c0b4afdcf680bac2f4ec2e //遷移到哪個節(jié)點,即目標節(jié)點
--slots 45 //遷移多少slot
--yes //無需輸入yes確認
不過非交互的遷移就不能使用多個源節(jié)點進行遷移slots了.
移除一個節(jié)點:
只要使用 del-node 命令即可:
redis-trib del-node 127.0.0.1:7000 `<node-id>`
第一個參數(shù)是任意一個節(jié)點的地址,第二個節(jié)點是你想要移除的節(jié)點地址。
使用同樣的方法移除主節(jié)點,不過在移除主節(jié)點前,需要確保這個主節(jié)點是空的. 如果不是空的,需要將這個節(jié)點的數(shù)據(jù)重新分片到其他主節(jié)點上.
替代移除主節(jié)點的方法是手動執(zhí)行故障恢復(fù),被移除的主節(jié)點會作為一個從節(jié)點存在,不過這種情況下不會減少集群節(jié)點的數(shù)量,也需要重新分片數(shù)據(jù)。