Redis Cluster學習筆記
Redis在3.0版正式引入了叢集這個特性。Redis叢集是一個分布式(distributed)、容錯(fault-tolerant)的 Redis記憶體K/V服務, 叢集可以使用的功能是普通單機 Redis 所能使用的功能的一個子集(subset),比如Redis叢集並不支援處理多個keys的命令,因為這需要在不同的節點間移動資料,從而達不到像Redis那樣的效能,在高負載的情況下可能會導致不可預料的錯誤。
Redis叢集的幾個重要特徵:
(1).Redis 叢集的分區特徵在於將鍵空間分拆了16384個槽位,每一個節點負責其中一些槽位。
(2).Redis提供一定程度的可用性,可以在某個節點宕機或者不可達的情況下繼續處理命令.
(3).Redis 叢集中不存在中心(central)節點或者代理(proxy)節點, 叢集的其中一個主要設計目標是達到線性可擴充性(linear scalability)。
1. Redis的資料分區(Sharding)
Redis 叢集的鍵空間被分割為 16384 (2^14)個槽(slot), 叢集的最大節點數量也是 16384 個(推薦的最大節點數量為 1000 個),同理每個主節點可以負責處理1到16384個槽位。
當16384個槽位都有主節點負責處理時,叢集進入”穩定“上線狀態,可以開始處理資料命令。當叢集沒有處理穩定點時,可以通過執行重配置(reconfiguration)操作,使得每個雜湊槽都只由一個節點進行處理。
重配置指的是將某個/某些槽從一個節點移動到另一個節點。一個主節點可以有任意多個從節點, 這些從節點用於在主節點發生網路斷線或者節點失效時, 對主節點進行替換。
叢集的使用公式CRC16(Key)&16383計算key屬於哪個槽:
HASH_SLOT = CRC16(key) mod 16384
CRC16其結果長度為16位。
下面關於Redis的文章您也可能喜歡,不妨參考下:
Ubuntu 14.04下Redis安裝及簡單測試
Redis主從複製基本配置
Redis叢集明細文檔
Ubuntu 12.10下安裝Redis(圖文詳解)+ Jedis串連Redis
Redis系列-安裝部署維護篇
CentOS 6.3安裝Redis
Redis安裝部署學習筆記
Redis設定檔redis.conf 詳解
2. Redis叢集節點
部分內容摘自附錄2。Redis 叢集中的節點不僅要記錄鍵和值的映射,還需要記錄集群的狀態,包括鍵到正確節點的映射。它還具有自動探索其他節點,識別工作不正常的節點,並在有需要時,在從節點中選舉出新的主節點的功能。
為了執行以上列出的任務, 叢集中的每個節點都與其他節點建立起了“叢集串連(cluster bus)”, 該串連是一個 TCP 串連, 使用二進位協議進行通訊。
節點之間使用 Gossip 協議 來進行以下工作:
a).傳播(propagate)關於叢集的資訊,以此來發現新的節點。
b).向其他節點發送 PING 資料包,以此來檢查目標節點是否正常運作。
c).在特定事件發生時,發送叢集資訊。
除此之外, 叢集串連還用於在叢集中發布或訂閱資訊。
叢集節點不能前端代理命令請求, 所以用戶端應該在節點返回 -MOVED
或者 -ASK
轉向(redirection)錯誤時, 自行將命令請求轉寄至其他節點。
用戶端可以自由地向叢集中的任何一個節點發送命令請求, 並可以在有需要時, 根據轉向錯誤所提供的資訊, 將命令轉寄至正確的節點, 所以在理論上來說, 用戶端是無須儲存叢集狀態資訊的。但如果用戶端可以將鍵和節點之間的映射資訊儲存起來, 可以有效地減少可能出現的轉向次數, 籍此提升命令執行的效率。
每個節點在叢集中由一個獨一無二的 ID標識, 該 ID 是一個十六進位表示的 160 位隨機數,在節點第一次啟動時由 /dev/urandom 產生。節點會將它的 ID 儲存到設定檔, 只要這個設定檔不被刪除, 節點就會一直沿用這個 ID 。一個節點可以改變它的 IP 和連接埠號碼, 而不改變節點 ID 。 叢集可以自動識別出IP/連接埠號碼的變化, 並將這一資訊通過 Gossip協議廣播給其他節點知道。
下面是每個節點都有的關聯資訊, 並且節點會將這些資訊發送給其他節點:
a).節點所使用的 IP 位址和 TCP 通訊埠號。
b).節點的標誌(flags)。
c).節點負責處理的雜湊槽。
b).節點最近一次使用叢集串連發送 PING 資料包(packet)的時間。
e).節點最近一次在回複中接收到 PONG 資料包的時間。
f).叢集將該節點標記為下線的時間。
g).該節點的從節點數量。
如果該節點是從節點的話,那麼它會記錄主節點的節點 ID 。 如果這是一個主節點的話,那麼主節點 ID 這一欄的值為 0000000。
在瞭解Redis Cluster的叢集基本特徵後,我們首先搭建出這個Redis Cluster叢集。
3. 安裝Redis 3.0.x
當前最新版為3.0.1
wget http://download.redis.io/releases/redis-3.0.1.tar.gztar xvzf redis-3.0.1.tar.gzcd redis-3.0.1/make -j#apt-get install tclmake test###將redis安裝到/usr/local/redis3上#cd src && make PREFIX=/usr/local/redis3 install###建立符號連結 #ls /usr/local/redis3/bin/redis-*/usr/local/redis3/bin/redis-benchmark /usr/local/redis3/bin/redis-check-dump /usr/local/redis3/bin/redis-sentinel/usr/local/redis3/bin/redis-check-aof /usr/local/redis3/bin/redis-cli /usr/local/redis3/bin/redis-server#for i in `cd /usr/local/redis3/bin; ls redis-*`doln -s /usr/local/redis3/bin/$i /usr/local/bin/$idone;#mkdir -p /usr/local/redis3/conf#ln -sf /usr/local/redis3/conf /etc/redis3###檢查版本資訊redis-cli -vredis-cli 3.0.1
4. Redis Cluster配置
運行在叢集模式的Redis執行個體與普通的Redis執行個體有所不同,叢集模式需要通過配置啟用cluster特性,開啟叢集模式後的Redis執行個體便可以使用叢集特有的命令和特性了.下面是一個最少選項的叢集的設定檔 : 注意如果使用的是單機測試,最好把cluster-config-file nodes.conf設定為對應的 連接埠 nodes-xxx.conf,還有就是 pid 設定為當前 目錄下 pidfile ./redis.pid
port 7001cluster-enabled yescluster-config-file nodes.confcluster-node-timeout 5000appendonly yes
檔案中的 cluster-enabled 選項用於開執行個體的叢集模式, 而 cluster-conf-file 選項則設定了儲存節點設定檔的路徑, 預設值為 nodes.conf。該節點設定檔無須人為修改,它由Redis叢集在啟動時自動建立, 並在有需要時自動進行更新。
若要讓叢集正常運作至少需要三個主節點,我們的環境中,每個主節點附帶一個從節點,所以一共六個節點。連接埠為7001-7006。
在/app/redis3, 並建立六個以連接埠號碼為名字的子目錄, 稍後我們在將每個目錄中運行一個 Redis 執行個體:
cd /app/redis3mkdir 7001 7002 7003 7004 7005 7006 cp /etc/redis3/conf/redis.conf /app/redis3/7001/......cp /etc/redis3/conf/redis.conf /app/redis3/7006/
將redis.conf裡的連接埠號碼修改為對應的連接埠。下面我們開啟對應的目錄,啟動redis執行個體即可,啟動的時候要進入到對應的目錄然後啟動。
cd /app/redis3/7001;nohup redis-server redis.conf &cd /app/redis3/7002;nohup redis-server redis.conf &......
執行個體列印的日誌顯示, 因為 nodes.conf 檔案不存在, 所以每個節點都為它自身指定了一個新的 ID ,
/app/redis3/7006# tail -f nohup.out27040:M 09 May 22:53:50.197 * No cluster configuration found, I'm 1984c27297c6ef50bbfcbd35c11b93cc40ba17e4/app/redis3/7006# cat nodes.conf d2b437ca8b9007dcdb63ac16210f6540860361e3 :0 myself,master - 0 0 0 connectedvars currentEpoch 0 lastVoteEpoch 0
現在我們已經有了六個正在運行中的 Redis 執行個體, 接下來我們需要使用這些執行個體來建立叢集。通過使用 Redis 叢集命令列工具 redis-trib , 編寫節點設定檔的工作可以非常容易地完成: redis-trib 位於 Redis 源碼的 src 檔案夾中, 它是一個 Ruby 程式, 這個程式通過向執行個體發送特殊命令來完成建立新叢集, ���查叢集, 或者對叢集進行重新分區(reshared)等工作。這裡通過create命令來建立叢集,指定replicas=1,即每一個主執行個體有一個從執行個體。redis-trib 會列印出一份預想中的配置給你看, 如果你覺得沒問題的話, 就可以輸入 yes , redis-trib 就會將這份配置應用到叢集當中,讓各個節點開始互相通訊,最後可以得到如下資訊
~/redis-3.0.1/src# apt-get install ruby gem~/redis-3.0.1/src# gem sources -a http://ruby.taobao.org/~/redis-3.0.1/src# gem install redis~/redis-3.0.1/src# cp redis-trib.rb /usr/local/redis3/bin/~/redis-3.0.1/src# ln -sf /usr/local/redis3/bin/redis-trib.rb /usr/bin/redis-trib.rb~/redis-3.0.1/src# 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:7006M: 1984c27297c6ef50bbfcbd35c11b93cc40ba17e4 127.0.0.1:7001 slots:0-5460 (5461 slots) masterM: 481e256be4c724f5a2c64a761e52b4be61ca45b4 127.0.0.1:7002 slots:5461-10922 (5462 slots) masterM: b5b652fa02d9999861e66c843b01fd2700c02adf 127.0.0.1:7003 slots:10923-16383 (5461 slots) masterS: 821ec823dc0c2d4f65319e84fe74157fb1014155 127.0.0.1:7004 replicates 1984c27297c6ef50bbfcbd35c11b93cc40ba17e4S: b3b8541b9520d707180d56a2fb3cf3ee6895ed10 127.0.0.1:7005 replicates 481e256be4c724f5a2c64a761e52b4be61ca45b4S: d2b437ca8b9007dcdb63ac16210f6540860361e3 127.0.0.1:7006 replicates b5b652fa02d9999861e66c843b01fd2700c02adfCan I set the above configuration? (type 'yes' to accept):[OK] All nodes agree about slots configuration.>>> Check for open slots...>>> Check slots coverage...[OK] All 16384 slots covered.
以上資訊的其中一部分可以通過向叢集中的任意節點(主節點或者從節點都可以)發送 CLUSTER NODES 命令來獲得。該命令還可以獲得節點 ID , IP 位址和連接埠號碼, 標誌(flag), 最後發送 PING 的時間, 最後接收 PONG 的時間, 串連狀態, 節點負責處理的槽。
redis-cli -p 7001 cluster nodes481e256be4c724f5a2c64a761e52b4be61ca45b4 127.0.0.1:7002 master - 0 1431186119174 2 connected 5461-10922b3b8541b9520d707180d56a2fb3cf3ee6895ed10 127.0.0.1:7005 slave 481e256be4c724f5a2c64a761e52b4be61ca45b4 0 1431186120677 5 connectedd2b437ca8b9007dcdb63ac16210f6540860361e3 127.0.0.1:7006 slave b5b652fa02d9999861e66c843b01fd2700c02adf 0 1431186119174 6 connectedb5b652fa02d9999861e66c843b01fd2700c02adf 127.0.0.1:7003 master - 0 1431186118673 3 connected 10923-16383821ec823dc0c2d4f65319e84fe74157fb1014155 127.0.0.1:7004 slave 1984c27297c6ef50bbfcbd35c11b93cc40ba17e4 0 1431186120176 4 connected1984c27297c6ef50bbfcbd35c11b93cc40ba17e4 127.0.0.1:7001 myself,master - 0 0 1 connected 0-5460
5. 串連Redis叢集
通過上面的輸出,我們可以看出Redis三個主節點的slot範圍。一個 Redis 用戶端可以向叢集中的任意節點(包括從節點)發送命令請求。我們首先串連第一個節點:
redis-cli -p 7001127.0.0.1:7001> set a 1 (error) MOVED 15495 127.0.0.1:7003127.0.0.1:7001> get a(error) MOVED 15495 127.0.0.1:7003127.0.0.1:7001> set b 1OK
節點會對命令請求進行分析和key的slot計算,並且會尋找這個命令所要處理的鍵所在的槽。如果要尋找的雜湊槽正好就由接收到命令的節點負責處理, 那麼節點就直接執行這個命令。
另一方面, 如果所尋找的槽不是由該節點處理的話, 節點將查看自身內部所儲存的雜湊槽到節點 ID 的映射記錄, 並向用戶端回複一個 MOVED 錯誤。上面的錯誤資訊包含鍵 x 所屬的雜湊槽15495, 以及負責處理這個槽的節點的 IP 和連接埠號碼 127.0.0.1:7003 。
雖然我們用Node ID來標識叢集中的節點, 但是為了讓用戶端的轉向操作儘可能地簡單, 節點在 MOVED 錯誤中直接返回目標節點的 IP 和連接埠號碼, 而不是目標節點的 ID 。用戶端應該記錄槽15495由節點127.0.0.1:7003負責處理“這一資訊, 這樣當再次有命令需要對槽15495執行時, 用戶端就可以加快尋找正確節點的速度。這樣,當叢集處於穩定點時,所有用戶端最終都會儲存有一個雜湊槽至節點的映射記錄,使得叢集非常高效: 用戶端可以直接向正確的節點發送命令請求, 無須轉向、代理或者其他任何可能發生單點故障(single point failure)的實體(entiy)。
更多詳情見請繼續閱讀下一頁的精彩內容: