Redis是目前大規模使用的緩存中間件,因爲它強大、高效、便捷的功能,獲得了普遍的使用。node
Redis在2015年發佈了3.0.0,官方就已經支持了redis cluster。redis cluster在設計的時候,就考慮到了去中心化、去中間件。也就是說,集羣中的每一個節點都是平等的關係,每一個節點都保存各自的數據和整個集羣的狀態。每一個節點都和其餘全部節點鏈接,並且這些鏈接保持活躍,這樣就保證了咱們只需鏈接集羣中的任意一個節點,就能夠獲取到其餘節點的數據。redis
Redis集羣是一個能夠在多個Redis節點之間進行數據共享的設施。Redis集羣不支持那些須要同時處理多個鍵的redis命令,由於執行這些命令須要在多個節點之間移動數據,而且在高負載的狀況下,這些命令將下降redis集羣的性能,並致使不可預測的行爲。算法
Redis集羣經過分區來提供必定程度的可用性,即便集羣中一部分節點失效或者沒法通訊,集羣也能夠繼續處理命令請求。docker
Redis是如何合理發呢配這些節點和數據的?數據庫
Redis並無採用傳統的一致性哈希來分配數據,而是採用了另外一種叫作哈希槽的方式分配的。Redis cluster默認分配了16384個slot,當咱們set一個key時,會採用CRC16算法(循環冗餘校驗碼)來獲取所屬的slot,而後將這個key分到哈希槽區間的節點山,具體算法:CRC16(key)%16384。vim
注意:必須是三個以上的主節點纔可建立羣集,不然羣集會失敗。緩存
Redis集羣在工做時其中某一臺主節點宕機後有其餘的master節點進行投票和選舉,而且投票的結果時一半以上才能肯定主節點宕機,若是主節點宕機一半以上整個集羣的狀態就是fail。這就是爲何至少須要三臺主節點纔可搭建Redis羣集環境。ruby
Redis羣集的好處:服務器
- 1)具備將數據自動切分split到多個節點上的能力;
- 2)當羣集中的一部分節點失效或者沒法進行通信時,仍然具備繼續處理命令請求的能力;
- 3)全部的rredis節點彼此互聯,內部使用二進制協議優化傳輸速度和帶寬;二進制協議:傳輸過程當中給有消息頭和消息實體。若是消息頭長度固定。經過解析消息頭就能夠獲得消息實體;
- 4)節點的fail是經過集羣中超過半數的節點檢測失效時才生效;
- 5)客戶端與redis節點直連,不須要中間proxy層,客戶端不須要鏈接集羣全部節點,鏈接集羣中任何一個可用節點便可;
Redis採用的之中哈希槽的分配方式有好也有壞,好處就是很清晰,好比:我想增長一個節點D,redis cluster的這種作法是從各個節點的前面各拿取一部分slot到D上。大體就會變成這樣:
節點A覆蓋1365-5460 節點B覆蓋6827-10922 節點C覆蓋12288-16383 節點D覆蓋01364,5461-6826,10923-12287 一樣刪除一個節點也是相似,移動完成後就能夠刪除這個 節點了;app
因此redis cluster就是這樣一個形狀,如圖:
Redis-cluster爲了保證數據的高可用性,加入了主從模式,一個主節點對應一個或多個從節點。主節點提供數據存取,從節點則是從主節點獲取數據備份;當主節點宕機後,就會由這個從節點中選取一個來充當主節點,從而保證羣集不會掛掉。
關於多臺Linux實現redis羣集能夠參考Redis數據庫羣集
因爲是使用單臺服務器實現集羣環境,因此就根據其端口來進行區分!
下載Redis羣集
[root@docker ~]# tar zxf redis-4.0.14.tar.gz -C /usr/local [root@docker ~]# cd /usr/local/redis-4.0.14/ [root@docker redis-4.0.14]# make && make install //編譯安裝redis [root@redis ~]# mkdir -p /usr/local/cluster/700{0..5} //因爲是在單臺建立多個節點,因此事先把這個目錄建立好,用於存放各個節點的配置信息 [root@docker ~]# cp /usr/local/redis-4.0.14/redis.conf /usr/local/cluster/7000 //將redis本來的配置文件複製一份 [root@docker ~]# vim /usr/local/cluster/7000/redis.conf //編譯7000節點的配置文件 92 port 7000 //修改監聽端口 158 pidfile /var/run/redis_7000.pid //修改pid文件名 672 appendonly yes //開啓aof持久化 676 appendfilename "appendonly-7000.aof" //修改持久化的配置文件名 814 cluster-enabled yes //開啓redis的羣集模式 822 cluster-config-file nodes-7000.conf //修改羣集的配置文件名 828 cluster-node-timeout 5000 //修改羣集的等待時間 [root@docker ~]# cd /usr/local/cluster/7000 [root@docker 7000]# redis-server redis.conf //必須進入相應的目錄啓動redis服務
不過啓動時,會出現這樣的錯誤,如圖:
[root@redis 7000]# vim /usr/local/cluster/7000/redis.conf //編寫7000節點的配置文件 136 daemonize yes //開啓守護進程讓其在後臺運行 [root@redis 7000]# echo 512 > /proc/sys/net/core/somaxconn [root@redis 7000]# echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf [root@redis 7000]# sysctl -p vm.overcommit_memory = 1 [root@redis 7000]# echo never > /sys/kernel/mm/transparent_hugepage/enabled //根據剛纔提示的警告信息對redis服務簡單進行一個優化
[root@redis 7000]# redis-server redis.conf //進入其目錄運行redis服務 [root@redis 7000]# cp redis.conf ../7001 [root@redis 7000]# cp redis.conf ../7002 [root@redis 7000]# cp redis.conf ../7003 [root@redis 7000]# cp redis.conf ../7004 [root@redis 7000]# cp redis.conf ../7005 //由於須要開啓六個節點,因此須要將其配置文件分爲六份 [root@redis 7000]# sed -i s/7000/7001/g ../7001/redis.conf [root@redis 7000]# sed -i s/7000/7002/g ../7002/redis.conf [root@redis 7000]# sed -i s/7000/7003/g ../7003/redis.conf [root@redis 7000]# sed -i s/7000/7004/g ../7004/redis.conf [root@redis 7000]# sed -i s/7000/7005/g ../7005/redis.conf //由於六個節點都是根據端口來區分,因此配置文件中只需修改以端口號命名的內容 [root@redis 7000]# cd ../7001 && redis-server redis.conf [root@redis 7001]# cd ../7002 && redis-server redis.conf [root@redis 7002]# cd ../7003 && redis-server redis.conf [root@redis 7003]# cd ../7004 && redis-server redis.conf [root@redis 7004]# cd ../7005 && redis-server redis.conf //都是進入其相應的目錄啓動服務 [root@redis 7005]# netstat -anpt | grep redis tcp 0 0 127.0.0.1:7004 0.0.0.0:* LISTEN 5615/redis-server 1 tcp 0 0 127.0.0.1:7005 0.0.0.0:* LISTEN 5620/redis-server 1 tcp 0 0 127.0.0.1:17000 0.0.0.0:* LISTEN 5524/redis-server 1 tcp 0 0 127.0.0.1:17001 0.0.0.0:* LISTEN 5592/redis-server 1 tcp 0 0 127.0.0.1:17002 0.0.0.0:* LISTEN 5605/redis-server 1 tcp 0 0 127.0.0.1:17003 0.0.0.0:* LISTEN 5610/redis-server 1 tcp 0 0 127.0.0.1:17004 0.0.0.0:* LISTEN 5615/redis-server 1 tcp 0 0 127.0.0.1:17005 0.0.0.0:* LISTEN 5620/redis-server 1 tcp 0 0 127.0.0.1:7000 0.0.0.0:* LISTEN 5524/redis-server 1 tcp 0 0 127.0.0.1:7001 0.0.0.0:* LISTEN 5592/redis-server 1 tcp 0 0 127.0.0.1:7002 0.0.0.0:* LISTEN 5605/redis-server 1 tcp 0 0 127.0.0.1:7003 0.0.0.0:* LISTEN 5610/redis-server 1 //查看端口都已經在監聽,剩下的17000這樣的端口是羣集之間溝通使用的
[root@redis 7005]# redis-cli -p 7000 //隨便指定一個端口進入redis終端 127.0.0.1:7000> CLUSTER INFO //查看羣集詳細信息 cluster_state:fail //發現如今是fail(失敗)的狀態 …………………… //省略 部份內容 127.0.0.1:7000> CLUSTER NODES //查看羣集節點 d554512885b2679d432d0d6b011c9ea56ea1ebeb :7000@17000 myself,master - 0 0 0 connected //發現加入羣集的節點只有7000這個節點 127.0.0.1:7000> exit [root@redis 7005]# redis-cli -h 127.0.0.1 -p 7000 cluster addslots {0..5461} OK [root@redis 7005]# redis-cli -h 127.0.0.1 -p 7001 cluster addslots {5462..10922} OK [root@redis 7005]# redis-cli -h 127.0.0.1 -p 7002 cluster addslots {10923..16383} OK //爲各個羣集階段分配hash槽 127.0.0.1:7000> CLUSTER MEET 127.0.0.1 7000 OK 127.0.0.1:7000> CLUSTER MEET 127.0.0.1 7001 OK 127.0.0.1:7000> CLUSTER MEET 127.0.0.1 7002 OK 127.0.0.1:7000> CLUSTER MEET 127.0.0.1 7003 OK 127.0.0.1:7000> CLUSTER MEET 127.0.0.1 7004 OK 127.0.0.1:7000> CLUSTER MEET 127.0.0.1 7005 OK //用來鏈接不一樣的開啓集羣支持的 Redis 節點,以進入工做集羣 [root@redis 7005]# redis-cli -p 7000 127.0.0.1:7000> CLUSTER INFO cluster_state:ok //再次查看羣集狀態發現已是「ok」的狀態 …………………… //省略部份內容 127.0.0.1:7000> CLUSTER NODES //再次查看羣集節點信息
如圖:
預設環境是7000是7003的主節點、7001是7004的主節點、7002是7005的主節點,操做以下:
[root@redis 7005]# redis-cli -p 7003 //鏈接7003的節點 127.0.0.1:7003> CLUSTER REPLICATE d554512885b2679d432d0d6b011c9ea56ea1ebeb OK //這個是7000的ID號 127.0.0.1:7003> exit [root@redis 7005]# redis-cli -p 7004 //鏈接7004的節點 127.0.0.1:7004> CLUSTER REPLICATE 182a55ee8b38afbf5b48209979f220dc4da7c14a OK //這個是7001的ID號 127.0.0.1:7004> exit [root@redis 7005]# redis-cli -p 7005 //鏈接7005的節點 127.0.0.1:7005> CLUSTER REPLICATE 82b62bda5b31d8ee27aee8d7320663ee86276e9f OK //這個是7002的ID號 127.0.0.1:7005> CLUSTER NODES //再次查看羣集節點的詳細信息
如圖:
[root@redis 7005]# redis-cli -p 7000 //進入節點插入數據進行測試 127.0.0.1:7000> set name lzj (error) MOVED 5798 127.0.0.1:7001 //發現出現錯誤,提示應該是7001的節點來存儲這個數據 127.0.0.1:7000> exit [root@redis 7005]# redis-cli -p 7000 -c //使用「-c」選項表示進入羣集中 127.0.0.1:7000> set name lzj //從新插入數據 -> Redirected to slot [5798] located at 127.0.0.1:7001 OK //提示將數據存放在7001節點上 127.0.0.1:7001> get name //獲取鍵所對應的值 "lzj"
[root@redis 7001]# cd ../7001 [root@redis 7001]# redis-cli -p 7001 shutdown //模擬7001節點故障 [root@redis 7001]# redis-cli -p 7000 127.0.0.1:7000> CLUSTER NODES //進入節點查看羣集節點的狀態 127.0.0.1:7004> get name "lzj"
如圖:
[root@redis 7001]# redis-server redis.conf //進入7001對應的目錄,啓動redis節點 [root@redis 7001]# redis-cli -p 7000 127.0.0.1:7000> CLUSTER NODES //進入羣集查看羣集狀態
如圖:
[root@redis ~]# yum -y install rpm-build openssl openssl-devel //安裝ruby所需依賴 [root@redis ~]# tar zxf ruby-2.3.1.tar.gz -C /usr/src cd [root@redis ~]# cd /usr/src/ruby-2.3.1/ [root@redis ruby-2.3.1]# ./configure --prefix=/usr/local/ruby && make && make install //編譯安裝ruby,可能時間較長 [root@redis ~]# ln -s /usr/local/ruby/bin/* /usr/local/bin //爲gem命令建立符號連接 [root@redis ~]# ln -s /usr/local/redis-4.0.14/src/* /usr/local/bin //爲redis經常使用命令建立符號連接 [root@redis ~]# gem install redis-3.3.0.gem //使用gem命令安裝Redis羣集必備軟件包
[root@redis ~]# redis-trib.rb check 127.0.0.1:7000 //檢查羣集節點狀態
如圖:
[root@redis ~]# mkdir /usr/local/cluster/7006 [root@redis ~]# cd /usr/local/cluster/7006 //建立相應目錄並進入 [root@redis 7006]# cp ../7000/redis.conf . [root@redis 7006]# sed -i s/7000/7006/g redis.conf //複製配置文件、並進行修改 [root@redis 7006]# redis-server redis.conf //修改7006節點的redis服務 [root@redis ~]# redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000 //將7006節點加入到7000節點羣集環境中(默認是master狀態) [root@redis ~]# redis-trib.rb check 127.0.0.1:7000 //再次查看羣集狀態
如圖:
截圖時,不當心擋上了,能夠發現7006這個節點是沒有槽點的,不能存儲數據的!
[root@redis ~]# redis-trib.rb reshard 127.0.0.1:7000 //分配7000這個羣集的槽點 How many slots do you want to move (from 1 to 16384)? 4096 //針對多少個節點進行操做 What is the receiving node ID?7add42108b3fc3e9c0af2846fb06ceaf8b172c87 //給7006節點,這裏輸入的是7006節點的ID號 Source node #1:all //從全部節點開始分配 [root@redis ~]# redis-trib.rb check 127.0.0.1:7000 //再次查看羣集狀態
如圖:
[root@redis ~]# mkdir /usr/local/cluster/7007 [root@redis ~]# cd /usr/local/cluster/7007 //建立相應目錄並進入 [root@redis 7007]# cp ../7000/redis.conf . [root@redis 7007]# sed -i s/7000/7007/g redis.conf //複製配置文件並進行修改 [root@redis 7007]# redis-server redis.conf //啓動7007節點redis服務 [root@redis ~]# redis-trib.rb add-node --slave 127.0.0.1:7007 127.0.0.1:7000 //往7000羣集中添加7007節點,並且指定其爲slave [root@redis ~]# redis-trib.rb check 127.0.0.1:7000 //查看羣集狀態
如圖:
[root@redis ~]# mkdir /usr/local/cluster/7008 [root@redis ~]# cd /usr/local/cluster/7008 [root@redis 7008]# cp ../7000/redis.conf . [root@redis 7008]# sed -i s/7000/7008/g redis.conf [root@redis 7008]# redis-server redis.conf //建立相應目錄並進行修改配置文件,啓動服務 [root@redis ~]# redis-trib.rb add-node --slave --master-id 7add42108b3fc3e9c0af2846fb06ceaf8b172c87 127.0.0.1:7008 127.0.0.1:7000 //向羣集中添加節點,指定其爲salve,並指定主節點ID號(7006節點的ID) [root@redis ~]# redis-trib.rb check 127.0.0.1:7000 //查看羣集狀態
如圖:
[root@redis ~]# redis-trib.rb reshard 127.0.0.1:7000 //對羣集節點進行操做 How many slots do you want to move (from 1 to 16384)? 4096 //針對多個節點進行操做 What is the receiving node ID? 7add42108b3fc3e9c0af2846fb06ceaf8b172c87 //這裏輸入將刪除的槽節點給那個節點(7006節點) Source node d554512885b2679d432d0d6b011c9ea56ea1ebeb //輸入刪除的節點 Source node done Do you want to proceed with the proposed reshard plan (yes/no)? yes //表示確認 [root@redis ~]# redis-trib.rb del-node 127.0.0.1:7000 d554512885b2679d432d0d6b011c9ea56ea1ebeb //刪除7000羣集中的7000節點 [root@redis ~]# redis-trib.rb check 127.0.0.1:7001 //查看羣集狀態
如圖:
——————————————本文到此結束,感謝閱讀————————————————————