redis學習系列(四)——redis高級應用(集群搭建、集群分區原理、集群操作)
05-25
redis學習系列(四)——redis高級應用(集群搭建、集群分區原理、集群操作)
創建並啟動集群進入redis安裝目錄的bin目錄下[root@localhost ~]# cd /usr/local/redis/bin/[root@localhost bin]#./redis-trib.rb create --replicas 1 192.168.2.128:7031 192.168.2.128:7032 192.168.2.128:7033 192.168.2.128:7034 192.168.2.128:7035 192.168.2.128:7036 命令的意義如下:給定 redis-trib.rb 程序的命令是 create,表示創建一個新的集群。選項 --replicas 1 表示為集群中的每個主節點創建一個從節點。之後跟著的其他參數則是實例的地址列表, 指定使用這些地址所指示的實例來創建新集群。 >>> Creating cluster
推薦閱讀:
來自專欄 編碼前線
Redis集群簡介
Redis 集群是3.0之後才引入的,在3.0之前,使用哨兵(sentinel)機制(本文將不做介紹,大家可另行查閱)來監控各個節點之間的狀態。Redis 集群可謂是讓很多人久等了。Redis 集群是一組能進行數據共享的Redis 實例(服務或者節點)的設施,集群可以使用的功能是普通單機 Redis 所能使用的功能的一個子集;Redis 集群通常具有高可用、可擴展性、分散式、容錯等特性。了解redis的集群後,這些晦澀的概念可結合redis的主從、集群分區和集群運維等角度理解體會。回到頂部Redis集群搭建創建集群文件夾
在/usr/local/下新建redis-cluster目錄並在redis-cluster下新建7031~7036共6個文件夾,這6個文件夾代表創建redis集群的6個節點。如下[root@localhost local]# mkdir -p /usr/local/redis-cluster[root@localhost redis-cluster]# mkdir 7031 7032 7033 7034 7035 7036拷貝修改配置文件將已有的/usr/local/redis/etc/下的redis.conf拷貝到新創建的7031目錄中[root@localhost etc]# cp redis.conf /usr/local/redis-cluster/7031[root@localhost 7031]# vi redis.conf修改項如下:(1)綁定埠,port 7031(2)綁定IP,bind 192.168.2.128
(3)指定數據存放路徑,dir /usr/local/redis-cluster/7031(4)啟動集群模式,cluster-enabled yes(5)指定集群節點配置文件,cluster-config-file nodes-7031.conf(6)後台啟動,daemonize yes(7)指定集群節點超時時間,cluster-node-timeout 5000(8)指定持久化方式,appendonly yes上面紅色項目最好全部設置,不然會出意想不到的錯誤,703x最好與節點文件夾保持一致。將7031的redis.conf改完後再拷貝到剩下的5個目錄中,然後只要全局替換redis.conf中的7031為相應的節點即可。安裝ruby由於Redis 集群客戶端實現很少,redis集群的啟動需要用到ruby實現的redis-trib.rb,所以我們需要先安裝ruby。
[root@localhost redis-cluster]# yum install ruby[root@localhost redis-cluster]# yum install rubygems[root@localhost redis-cluster]# gem install redis啟動redis實例[root@localhost redis-cluster]# /usr/local/redis/bin/redis-server /usr/local/redis-cluster/7031/redis.conf 分別啟動6個redis實例。也可以用腳本循環啟動,這樣更方便省時[root@localhost redis-cluster]#
for((i=1;i<=6;i++)); do /usr/local/redis/bin/redis-server /usr/local/redis-cluster/703$i/redis.conf; done 查看redis實例是否啟動成功 [root@localhost redis-cluster]# netstat -tunpl | grep redis-server#或者[root@localhost redis-cluster]# ps -ef | grep redis-server>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:192.168.2.128:7031192.168.2.128:7032192.168.2.128:7033Adding replica 192.168.2.128:7034 to 192.168.2.128:7031Adding replica 192.168.2.128:7035 to 192.168.2.128:7032Adding replica 192.168.2.128:7036 to 192.168.2.128:7033......[OK] All nodes agree about slots configuration.>>> Check for open slots...
>>> Check slots coverage...[OK] All 16384 slots covered. 「All 16384 slots covered.」表示集群中的 16384 個槽都有至少一個主節點在處理, 集群運作正常。從列印出來的信息也可以看出,7031,7032,7033是主節點,其它三個是從節點。客戶端連接集群集群啟動成功後,我們就可以用任意一個客戶端連接集群了,如下 [root@localhost bin]# /usr/local/redis/bin/redis-cli -c -h 192.168.2.128 -p 7031192.168.2.128:7031> info# Server
redis_version:3.2.0redis_git_sha1:00000000redis_git_dirty:0redis_build_id:f8fcffd133fe3364redis_mode:clusteros:Linux 2.6.32-504.el6.x86_64 x86_64arch_bits:64 可以使用 cluster info命令查看集群信息,cluster nodes命令查看集群節點信息。集群關閉
關閉集群需要逐個關閉[root@localhost redis-cluster]#for((i=1;i<=6;i++)); do /usr/local/redis/bin/redis-cli -c -h 192.168.2.128 -p 703$i shutdown; done 如果重新啟動集群報以下錯誤 [ERR] Node 192.168.2.128:7031 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0. 需要清除殺掉redis實例,然後刪除每個節點下的臨時數據文件appendonly.aof,dump.rdb,nodes-703x.conf,然後再重新啟動redis實例即可啟動集群。 [root@localhost redis-cluster]#for((i=1;i<=6;i++)); do cd 703$i; rm -rf appendonly.aof; rm -rf dump.rdb; rm -rf nodes-703$i.conf; cd ..; done 集群測試下面我們先來體驗一下集群的set,get簡單操作,後面我們會進一步學習集群的更多操作。 192.168.2.128:7031> set name "zhangsan"-> Redirected to slot [5798] located at 192.168.2.128:7032OK192.168.2.128:7032> set age 20-> Redirected to slot [741] located at 192.168.2.128:7031OK192.168.2.128:7031> set sex "man"OK192.168.2.128:7031> 如果在連接客戶端的時候不加-c選項set key時則會報MOVED 的錯誤: [root@localhost bin]# /usr/local/redis/bin/redis-cli -h 192.168.2.128 -p 7031192.168.2.128:7031> set name "zhangsan"(error) MOVED 5798 192.168.2.128:7032192.168.2.128:7031> set age 20OK192.168.2.128:7031> set sex "man"OK192.168.2.128:7031> 來看看取值又是怎麼樣 192.168.2.128:7031> get name-> Redirected to slot [5798] located at 192.168.2.128:7032"zhangsan"192.168.2.128:7032> get age-> Redirected to slot [741] located at 192.168.2.128:7031"20"192.168.2.128:7031> get sex"man"192.168.2.128:7031> 可以看到,客戶端連接加-c選項的時候,存儲和提取key的時候不斷在7031和7032之間跳轉,這個稱為客戶端重定向。之所以發生客戶端重定向,是因為Redis Cluster中的每個Master節點都會負責一部分的槽(slot),存取的時候都會進行鍵值空間計算定位key映射在哪個槽(slot)上,如果映射的槽(slot)正好是當前Master節點負責則直接存取,否則就跳轉到其他Master節點負的槽(slot)中存取,這個過程對客戶端是透明的。繼續看下文的集群分區原理。回到頂部Redis集群分區原理槽(slot)的基本概念從上面集群的簡單操作中,我們已經知道redis存取key的時候,都要定位相應的槽(slot)。Redis 集群鍵分布演算法使用數據分片(sharding)而非一致性哈希(consistency hashing)來實現: 一個 Redis 集群包含 16384 個哈希槽(hash slot), 它們的編號為0、1、2、3……16382、16383,這個槽是一個邏輯意義上的槽,實際上並不存在。redis中的每個key都屬於這 16384 個哈希槽的其中一個,存取key時都要進行key->slot的映射計算。下面我們來看看啟動集群時候列印的信息: >>> Creating cluster>>> Performing hash slots allocation on 6 nodes...Using 3 masters:192.168.2.128:7031192.168.2.128:7032192.168.2.128:7033Adding replica 192.168.2.128:7034 to 192.168.2.128:7031Adding replica 192.168.2.128:7035 to 192.168.2.128:7032Adding replica 192.168.2.128:7036 to 192.168.2.128:7033M: bee706db5ae182c5be9b9bdf94c2d6f3f8c8ec5c 192.168.2.128:7031 slots:0-5460 (5461 slots) masterM: 72826f06dbf3be163f2f456ca24caed76a15bdf4 192.168.2.128:7032 slots:5461-10922 (5462 slots) masterM: ab6e9d1dfc471225eef01e57be563157f81d26b3 192.168.2.128:7033 slots:10923-16383 (5461 slots) master......[OK] All nodes agree about slots configuration.>>> Check for open slots...>>> Check slots coverage...[OK] All 16384 slots covered. 從上面信息可以看出,創建集群的時候,哈希槽被分配到了三個主節點上,從節點是沒有哈希槽的。7031負責編號為0-5460 共5461個 slots,7032負責編號為 5461-10922共5462 個 slots,7033負責編號為10923-16383 共5461個 slots。鍵-槽映射演算法和memcached一樣,redis也採用一定的演算法進行鍵-槽(key->slot)之間的映射。memcached採用一致性哈希(consistency hashing)演算法進行鍵-節點(key-node)之間的映射,而redis集群使用集群公式來計算鍵 key 屬於哪個槽: HASH_SLOT(key)= CRC16(key) % 16384 其中 CRC16(key) 語句用於計算鍵 key 的 CRC16 校驗和 。key經過公式計算後得到所對應的哈希槽,而哈希槽被某個主節點管理,從而確定key在哪個主節點上存取,這也是redis將數據均勻分布到各個節點上的基礎。 鍵-槽-節點(key->slot->node)映射示意圖集群分區好處無論是memcached的一致性哈希演算法,還是redis的集群分區,最主要的目的都是在移除、添加一個節點時對已經存在的緩存數據的定位影響儘可能的降到最小。redis將哈希槽分布到不同節點的做法使得用戶可以很容易地向集群中添加或者刪除節點, 比如說:l 如果用戶將新節點 D 添加到集群中, 那麼集群只需要將節點 A 、B 、 C 中的某些槽移動到節點 D 就可以了。l 與此類似, 如果用戶要從集群中移除節點 A , 那麼集群只需要將節點 A 中的所有哈希槽移動到節點 B 和節點 C , 然後再移除空白(不包含任何哈希槽)的節點 A 就可以了。因為將一個哈希槽從一個節點移動到另一個節點不會造成節點阻塞, 所以無論是添加新節點還是移除已存在節點, 又或者改變某個節點包含的哈希槽數量, 都不會造成集群下線,從而保證集群的可用性。下面我們就來學習下集群中節點的增加和刪除。回到頂部集群操作集群操作包括查看集群信息,查看集群節點信息,向集群中增加節點、刪除節點,重新分配槽等操作。查看集群信息cluster info 查看集群狀態,槽分配,集群大小等,cluster nodes也可查看主從節點。 192.168.2.128:7031> cluster infocluster_state:okcluster_slots_assigned:16384cluster_slots_ok:16384cluster_slots_pfail:0cluster_slots_fail:0cluster_known_nodes:6cluster_size:3cluster_current_epoch:6cluster_my_epoch:1cluster_stats_messages_sent:119cluster_stats_messages_received:119192.168.2.128:7031>新增節點(1)新增節點配置文件執行下面的腳本創建腳本配置文件 [root@localhost redis-cluster]# mkdir /usr/local/redis-cluster/7037 && cp /usr/local/redis-cluster/7031/redis.conf /usr/local/redis-cluster/7037/redis.conf && sed -i "s/7031/7037/g" /usr/local/redis-cluster/7037/redis.conf (2)啟動新增節點 [root@localhost bin]# /usr/local/redis/bin/redis-server /usr/local/redis-cluster/7037/redis.conf (3)添加節點到集群現在已經添加了新增一個節點所需的配置文件,但是這個這點還沒有添加到集群中,現在讓它成為集群中的一個主節點 [root@localhost redis-cluster]# cd /usr/local/redis/bin/[root@localhost bin]# ./redis-trib.rb add-node 192.168.2.128:7037 192.168.2.128:7036>>> Adding node 192.168.2.128:7037 to cluster 192.168.2.128:7036>>> Performing Cluster Check (using node 192.168.2.128:7036)S: 2c8d72f1914f9d6052065f7e9910cc675c3c717b 192.168.2.128:7036 slots: (0 slots) slave replicates 6dbb4aa323864265c9507cf336ef7d3b95ea8d1bM: 6dbb4aa323864265c9507cf336ef7d3b95ea8d1b 192.168.2.128:7033 slots:10923-16383 (5461 slots) master 1 additional replica(s)S: 791a7924709bfd7ef5c36d9b9c838925e41e3c2e 192.168.2.128:7034 slots: (0 slots) slave replicates d9e3c78a7c49689c29ab67a8a17be9d95cb08452M: d9e3c78a7c49689c29ab67a8a17be9d95cb08452 192.168.2.128:7031 slots:0-5460 (5461 slots) master 1 additional replica(s)M: 69b63d8db629fa8a689dd1ed25ed941c076d4111 192.168.2.128:7032 slots:5461-10922 (5462 slots) master 1 additional replica(s)S: e669a91866225279aafcac29bf07b826eb5be91c 192.168.2.128:7035 slots: (0 slots) slave replicates 69b63d8db629fa8a689dd1ed25ed941c076d4111[OK] All nodes agree about slots configuration.>>> Check for open slots...>>> Check slots coverage...[OK] All 16384 slots covered.>>> Send CLUSTER MEET to node 192.168.2.128:7037 to make it join the cluster.[OK] New node added correctly.[root@localhost bin]# ./redis-trib.rb add-node 命令中,7037 是新增的主節點,7036 是集群中已有的從節點。再來看看集群信息 192.168.2.128:7031> cluster infocluster_state:okcluster_slots_assigned:16384cluster_slots_ok:16384cluster_slots_pfail:0cluster_slots_fail:0cluster_known_nodes:7cluster_size:3cluster_current_epoch:6cluster_my_epoch:1cluster_stats_messages_sent:11256cluster_stats_messages_received:11256 (4)分配槽從添加主節點輸出信息和查看集群信息中可以看出,我們已經成功的向集群中添加了一個主節點,但是這個主節還沒有成為真正的主節點,因為還沒有分配槽(slot),也沒有從節點,現在要給它分配槽(slot) [root@localhost bin]# ./redis-trib.rb reshard 192.168.2.128:7031>>> Performing Cluster Check (using node 192.168.2.128:7031)M: 1a544a9884e0b3b9a73db80633621bd90ceff64a 192.168.2.128:7031 ......[OK] All nodes agree about slots configuration.>>> Check for open slots...>>> Check slots coverage...[OK] All 16384 slots covered.How many slots do you want to move (from 1 to 16384)? 1024What is the receiving node ID? 系統提示要移動多少個配槽(slot),並且配槽(slot)要移動到哪個節點,任意輸入一個數,如1024,再輸入新增節點的ID cf48228259def4e51e7e74448e05b7a6c8f5713f. What is the receiving node ID? cf48228259def4e51e7e74448e05b7a6c8f5713fPlease 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: 然後提示要從哪幾個節點中移除1024個槽(slot),這裡輸入『all』表示從所有的主節點中隨機轉移,湊夠1024個哈希槽,然後就開始從新分配槽(slot)了。從新分配完後再次查看集群節點信息 可見,0-340 5461-5802 10923-11263的槽(slot)被分配給了新增加的節點。三個加起來剛好1024個槽(slot)。(5)指定從節點現在從節點7036的主節點是7033,現在我們要把他變為新增加節點(7037)的從節點,需要登錄7036的客戶端[root@localhost bin]# /usr/local/redis/bin/redis-cli -c -h 192.168.2.128 -p 7036192.168.2.128:7036> cluster replicate cf48228259def4e51e7e74448e05b7a6c8f5713fOK 再來查看集群節點信息 可見,7036成為了新增節點7037的從節點。刪除節點指定刪除節點的ID即可,如下[root@localhost bin]#./redis-trib.rb del-node 192.168.2.128:7037 a56461a171334560f16652408c2a45e629d268f6>>> Removing node a56461a171334560f16652408c2a45e629d268f6 from cluster 192.168.2.128:7037>>> Sending CLUSTER FORGET messages to the cluster...>>> SHUTDOWN the node.[root@localhost bin]# 集群操作小結從上面過程可以看出,添加節點、分配槽、刪除節點的過程,不用停止集群,不阻塞集群的其他操作。命令小結 #向集群中添加節點,7037是新增節點,7036是集群中已有的節點./redis-trib.rb add-node 192.168.2.128:7037 192.168.2.128:7036#重新分配槽./redis-trib.rb reshard 192.168.2.128:7031#指定當前節點的主節點cluster replicate cf48228259def4e51e7e74448e05b7a6c8f5713f#刪除節點./redis-trib.rb del-node 192.168.2.128:7037 a56461a171334560f16652408c2a45e629d268f6 到此,redis的集群搭建、分區原理、集群增加節點以及刪除節點的主要內容已經簡要介紹完畢。推薦閱讀:
※redis之父的博客翻譯-Redis中的LRU演算法改進
※200G的數據,主要是查詢操作,酷睿I5個人PC,應該選擇什麼資料庫來存儲?
※隊列是什麼意思?
※Redis集群的高可用測試(含Jedis客戶端的使用)