Redis 集羣是Redis 的一個分佈式實現,它是一個網狀結構,每一個節點都經過 TCP 鏈接跟其餘每一個節點鏈接。如今來看看Redis集羣實現了哪些目標?node
那麼Redis集羣環境與非分佈式Redis環境在功能上有沒有什麼不一樣的呢?git
在進入集羣環境搭建時,先介紹集羣的一些基本概念,例如節點、槽等等。github
節點(node)能夠說是構成集羣的基本元素.一般一個Redis集羣中包含了多個節點,每一個節點都有一個惟一的名字。redis
節點名字是一個十六進制表示的160 bit 隨機數,這個隨機數是節點第一次啓動時得到的(一般是用 /dev/urandom)。 節點會把它的ID保存在配置文件裏,之後永遠使用這個ID.若是想要更換ID有以下兩種方式:算法
CLUSTER RESET
命令。那麼這個節點ID有什麼用處呢?數據庫
節點ID是用於每一個節點。經過節點ID能夠檢測到節點 IP 或端口的變化。centos
若是節點發生了 IP 或端口變化時,其餘節點是如何得知的呢?安全
集羣會使用gossip 協議來發布廣播消息,通知配置變動。ruby
節點與節點之間知道對方的哪些信息?bash
咱們能夠經過使用CLUSTER NODES
命令能夠得到以上的一些信息,以下
Redis集羣經過分片的方式來保存數據庫中的鍵值對:整個鍵空間被分割爲 16384 槽(slot),每一個鍵都將存放在 16384 槽(slot)的其中一個位置上。
那麼是什麼決定一個鍵所存放的位置呢?
下方就是計算鍵存放的位置的算法。
HASH_SLOT = CRC16(key) mod 16384
經過CRC16算法獲取鍵的16位輸出結果,而後再對 16384 取餘,結果就是鍵所在的位置。
既然整個鍵空間被分割爲 16384 槽(slot),那麼是如何將這些槽分配給不一樣的節點的?
能夠經過如下命令將槽分片
CLUSTER ADDSLOTS slot1 [slot2] … [slotN]
本文搭建的集羣環境有3個主節點,每一個主節點都有兩個從節點,架構圖以下
關於集羣的配置以下
################################ REDIS CLUSTER ############################### cluster-enabled yes cluster-config-file nodes-6379.conf cluster-node-timeout 5000
cluster-enabled
表示是否開啓集羣模式
cluster-conf-file
表示保存節點配置文件的路徑
cluster-node-timeout
表示節點超時時間
完整的配置文件在https://github.com/rainbowda/learnWay/tree/master/learnRedis/cluster ,有須要的能夠去下載
因爲採用一個服務器運行三個Redis實例,因此每一個節點的配置有些許不一樣,像端口號、文件位置、文件名稱等等。這裏就不將每一個配置文件貼出來了,Github上有主節點和兩個從節點的配置文件。
我在redis文件夾下建立一個cluster文件夾,而後在cluster文件夾下建立一個master文件,存放主節點的配置文件master.conf和一些其餘文件;再而後建立兩個從節點文件7001和7002,也是存放配置文件等。
mkdir cluster cd cluster mkdir master 7001 7002
將配置文件拷貝到相應文件夾後,根據配置文件啓動Redis,這裏就不在說明了。
咱們已經有九個正在運行中的 Redis 實例 ,接下來須要使用這些實例來建立集羣 。Redis中提供集羣命令行工具 redis-trib 來簡化集羣操做
在執行redis-trib.rb文件以前須要安裝ruby環境,嫌麻煩能夠直接運行下面命令
yum install centos-release-scl-rh yum install rh-ruby23 -y scl enable rh-ruby23 bash gem install redis
注:若是直接運行yum install ruby
命令時,再運行gem install redis
會顯示redis requires Ruby version >= 2.2.2
錯誤
執行命令以下
./redis-trib.rb create --replicas 2 192.168.17.101:6379 192.168.17.102:6379 192.168.17.103:6379 192.168.17.101:7001 192.168.17.101:7002 192.168.17.102:7001 192.168.17.102:7002 192.168.17.103:7001 192.168.17.103:7002
命令中的create表示建立集羣 ,參數 replicas表示須要一個主節點有幾個從節點 ,後面就是節點ip和端口號。
命令執行後,會輸出已下內容,內容裏面包括主從節點的信息
接下來須要用戶輸入yes確認
輸入yes後, redis-trib 就會將這份配置應用到集羣當中,讓各個節點開始互相通信,最後能夠獲得以下信息:
當輸出已下內容時,表示集羣環境已經搭建好了
[OK] All 16384 slots covered
接下來輸入cluster info
命令看看集羣狀態,輸出的結果以下
在使用redis-trib建立集羣時,咱們並不知道其內部發生了什麼,接下來我將簡單介紹下其過程。
yes
確認分配方案。yes
以後,便開始執行分配方案。大體的過程如上,接下來介紹下cluster meet 命令
在沒有使用 CLUSTER MEET 命令時,每一個節點都是相互獨立的, 它們都處於一個只包含本身的集羣當中,經過使用 CLUSTER MEET 命令能夠將各個獨立的節點鏈接起來, 構成一個包含多個節點的集羣 。使用 CLUSTER MEET 命令的格式以下
CLUSTER MEET <ip> <port>
看看這個命令的實現
場景:有A(192.168.17.101)和B(192.168.17.102)兩個節點,在B節點的客戶端輸入CLUSTER MEET 192.168.17.101 6379
,表示B加入到A所在的集羣中。A收到命令後便開始執行如下步驟
節點的握手過程以下
這裏將模擬一個主節點故障,經過向主節點發送DEBUG SEGFAULT 命令來實現主節點故障效果。
在主節點101上執行DEBUG SEGFAULT命令以後,到103客戶端上查看節點狀態
能夠從上圖中看出101主節點多了個fail狀態,並且103的一個從節點7001變成了主節點。如今再讓101從新上線,再次查看狀態
能夠看到以前的101主節點變成了從節點。好了接下來看看集羣是怎麼發現故障及故障如何轉移的。
集羣是經過什麼方式來發現某個節點出現故障?
答:能夠分爲以下幾個步驟.
定義:發送PING消息的節點-->節點A;接受PING消息的節點-->節點B
NODE_TIMEOUT
時間內返回PONG消息,那麼節點A會將B節點標記爲PFAIL** (疑似下線狀態)NODE_TIMEOUT *FAIL_REPORT_VALIDITY_MULT
這個時間內是處於 PFAIL 狀態。那麼節點A會標記節點 B 爲 FAIL (已下線狀態)。故障轉移步驟:
SLAVEOF no one
命令,成爲新的主節點如下就是發生故障出現日誌內容
2169:M 31 Jul 21:06:20.873 * Marking node 3c29beb7984b40a8c19b580362a0daf29dc349fb as failing (quorum reached). 2169:M 31 Jul 21:06:20.873 # Cluster state changed: fail 2169:M 31 Jul 21:06:21.546 # Failover auth granted to aba761321b40112c0b8de29d810767a40c59d27b for epoch 10 2169:M 31 Jul 21:06:21.586 # Cluster state changed: ok 2169:M 31 Jul 21:13:05.849 * Clear FAIL state for node 3c29beb7984b40a8c19b580362a0daf29dc349fb: master without slots is reachable again.
這篇文章主要介紹集羣搭建和故障檢測轉移,固然集羣中還有其餘知識點像MOVED 重定向、ASK 重定向和從新分片等功能,這些功能官方文檔都有相應的資料。
Redis官網:https://redis.io
Redis中文網:http://www.redis.cn
本篇的集羣配置文件:https://github.com/rainbowda/learnWay/tree/master/learnRedis/cluster