1. 程式人生 > >redis cluster叢集搭建

redis cluster叢集搭建

一、環境準備

採用的Vmware pro 12虛擬機器,建立一個centos7最小化版本節點,在上面安裝redis-4.0.6,再複製兩個redis例項。然後通過vmware克隆一個新的節點。從而保證三主三從共6個redis例項。

二、操作步驟

1.在每臺centos機器的/usr/local資料夾下建立redis-cluster資料夾作為redis叢集根目錄
cd /usr/local && mkdir redis-cluster
2.在redis-cluster資料夾下安裝3個redis例項,主要是將原始碼包裡的redis.conf拷貝過來,修改幾個引數,如下
port  7000
//自定義每個redis例項埠如7000~7006 protected-mode no //預設保護模式yes,修改為no #bind 127.0.0.1 //預設安全保護,只能訪問本機 daemonize yes //redis後臺執行 cluster-enabled yes //開啟叢集 把註釋#去掉 #下面項實驗時未進行設定 pidfile ./redis_7000.pid //pidfile檔案對應7000,7001,7002 cluster-config-file nodes_7000.conf //叢集的配置 配置檔案首次啟動自動生成 7000,7001,7002
cluster-node-timeout 15000 //請求超時 預設15秒,可自行設定 appendonly yes //aof日誌開啟 有需要就開啟,它會每次寫操作都記錄一條日誌
3.將原始碼包裡的ruby指令碼redis-trib.rb拷貝到redis-cluster資料夾下
cp redis-trib.rb /usr/local/redis-cluster/
4.安裝ruby環境
yum -y install ruby ruby-devel rubygems rpm-build
gem install redis
5.啟動每個redis例項
redis-server
redis.conf ps 檢查程序: ps -ef|grep redis
6.執行ruby指令碼
redis-trib.rb create --replicas 1 192.168.1.80:7000 192.168.1.80:7001 192.168.1.80:7002 192.168.1.81:7003 192.168.1.81:7004 192.168.1.81:7005

如果提示:All 16384 slots covered,表示叢集啟動成功

三、碰到的坑

1.centos7無法訪問外網
我這裡宿主機用的win10 + wifi上網
1)首先在宿主機cmd 
ipconfig /all  
檢視本機網路情況,要記錄下本機的ip和dns,後面centos7要用
2)然後vmware 虛擬網路編輯器選擇的Nat模式,注意子網IP要設定跟宿主機ip不是一個網段,如宿主機ip:192.168.10.155,那麼這裡VMnet8的ip可以設定192.168.1.0,子網:255.255.255.0;nat設定裡設定閘道器與VMnet8的ip同網段,末尾只要與它ip不一致並且不是0就行,如192.168.1.2.
記住這個閘道器,因為後面centos設定網路配置檔案時,裡面的gateway就是寫的這個。
對於埠轉發,我設定了一個22埠,不知道有沒有用~...
主機埠 22 型別 tcp 虛擬機器IP地址 宿主機ip:22 
這裡宿主機ip就是cmd裡記得 192.168.10.155
3)在修改/etc/sysconfig/network-scripts/ifcfg-e***檔案,如ifcfg-eno16777736或者ifcfg-etho33,主要修改一下幾項:
    BOOTPROTO=static #選項還有dhcp:自動分配ip,這裡是指定靜態ip,防止重啟ip變化
    IPADDR=192.168.1.80 #這裡要設定的ip要跟vmnet8設定的閘道器一個網段
    NETMASK=255.255.255.0 #指定子網掩碼
    ONBOOT=yes #centos啟動就自動網路連線
    #另外我碰到一個重啟網路服務,dns重置的問題,將dns配置以/etc/resolv.conf為主,這裡另外設定的
    PEERDNS=no
    NM_CONTROLLED="no"
4)設定/etc/resolv.conf
nameserver 219.141.136.10 #這裡就是cmd記錄的宿主機閘道器
    #google dns
    nameserver 8.8.8.8
    nameserver 4.4.4.4
如果報錯:failed to start lsb:bring up/down networking.
解決辦法:將NetworkManager關掉
systemctl stop NetworkManager
systemctl disable NetworkManager
Removed symlink /etc/systemd/system/multi-user.target.wants/NetworkManager.service.
Removed symlink /etc/systemd/system/dbus-org.freedesktop.NetworkManager.service.
Removed symlink /etc/systemd/system/dbus-org.freedesktop.nm-dispatcher.service.
重新啟動網路:
systemctl start network.service
ifconfig |grep eno
如果克隆的centos找不到ip,則按照以下步驟解決:
1.由於在CentOS7-1中,我關閉了NetworkManager.service服務,並設定了開機不啟動。再CentOS7-2中,先開啟NetworkManager服務。
# systemctl start NetworkManager.service
2.使用ifconfig或者 ip addr檢視網絡卡資訊,發現一個名為ens33的網絡卡。記下MAC地址,例如00:0c:29:84:13:a1
3.進入目錄/etc/sysconfig/netowrk-scripts中。將ifcfg-eno16777736改名為ifcfg-ens33。
# mv ifcfg-eno16777736 ifcfg-ens33
4.修改ifcfg-ens33
# vi ifcfg-ens33
TYPE="Ethernet"
BOOTPROTO="static"
NAME="ens33"
HWADDR="00:0c:29:84:13:a1"
DEVICE="ens33"
ONBOOT="yes"
IPADDR=192.168.1.81
NETMASK=255.255.255.0
GATEWAY=192.168.1.2
DNS1=219.141.136.10
5.刪除檔案 
# rm -f /etc/udev/rules.d/90-eno-fix.rules
6.關閉NetworkManager服務, 
# systemctl stop NetworkManager.service
7.重啟網路服務
# systemctl restart network.service

ps 防火牆都是禁用狀態

systemctl stop firewalld.service #停止firewall
systemctl disable firewalld.service  #禁止開機啟動
至此,centos機應該訪問外網

2.gem install redis,發現redis需要的ruby版本要大於2.2.0

解決辦法是 先安裝rvm,再把ruby版本提升至2.3.3
1.安裝curl
sudo yum install curl
2. 安裝RVM
curl -L get.rvm.io | bash -s stable 
3. 
source /usr/local/rvm/scripts/rvm
4. 檢視rvm庫中已知的ruby版本
rvm list known
5. 安裝一個ruby版本
rvm install 2.3.3
6. 使用一個ruby版本
rvm use 2.3.3
7. 設定預設版本
rvm remove 2.0.0
8. 解除安裝一個已知版本
ruby --version
9. 再安裝redis就可以了
gem install redis

四、叢集命令

1.建立叢集

redis-trib.rb create --replicas 1 192.168.1.80:7000 192.168.1.80:7001 192.168.1.80:7002 192.168.1.81:7003 192.168.1.81:7004 192.168.1.81:7005
其中:create //表示建立叢集功能
--replicas 1 //表示為每個主節點自動分配一個從節點.也就是自動分配三個主節點和三個從節點.

2.檢視叢集狀態
登入客戶端 redis-cli -p 7002(可以任意一個)

cluster info 

3.檢視叢集節點資訊
登入客戶端 redis-cli -p 7002(可以任意一個)

cluster nodes

4.檢查叢集狀態
5.修復叢集狀態
6.增加redis節點
1) 建立兩個例項目錄,一個例項做為新節點的主例項,一個例項做為新節點的從例項
2)修改相應的redis.conf,修改埠等資訊
3)啟動這兩個例項
4)增加節點

redis-trib.rb add-node 192.168.1.81:7007 192.168.1.80:7001
PS:這個IP:PORT可以是叢集裡邊兒任意一個主節點的IP和埠
redis-cli -c -p 7002 cluster nodes
36d53c7f1896838249c0b4afdcf680bac2f4ec2e 192.168.1.81:7007 master - 0 1463476564369 0 connected

發現7007這個例項已經做為主節點加到叢集裡邊兒來了.

5)7008做為7007的從節點也加入到叢集裡邊兒來, 注意記住7007這個主節點的節點id.從節點加入到叢集的時候要用到.

redis-trib.rb add-node --slave --master-id 36d53c7f1896838249c0b4afdcf680bac2f4ec2e 192.168.1.81:7008 192.168.1.80:7001

6)重新分片

redis-trib.rb reshard 192.168.1.80:7001
//PS: 這條命令是互動的,按照提示操作即可.
How many slots do you want to move (from 1 to 16384)?4096  //輸入一個數,這個4096表示遷移多少個slots數
What is the receiving node ID? 36d53c7f1896838249c0b4afdcf680bac2f4ec2e //輸入目標節點ID,表示遷移到哪個目標節點
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表示從老的所有節點進行重分配,湊夠4096個slots給到新節點.
也可以輸入源節點id, 可以輸入多個源節點id,最後輸入done.就開始從你輸入的源節點id的節點進行遷移了.

7.刪除redis節點(主節點 7001)
首先必須確保這個節點沒有擁有任何一個slots
1)檢視叢集節點資訊

redis-cli -c -p 7002 cluster nodes
a2eee0ea546f2c3701b08981737c07938039857c 192.168.1.80:7001 master - 0 1463477001334 1 connected 1365-5460

2)重新分片

redis-trib.rb reshard 192.168.1.80:7001
How many slots do you want to move (from 1 to 16384)?16384 //輸入一個大於或等於7001節點所擁有的slots數的數即可.
What is the receiving node ID? 8ab3d14eba181c06dc8826bea0db1becdead2533 //接收這些slots的目標節點,這裡是7002節點
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:a2eee0ea546f2c3701b08981737c07938039857c //因為我們要刪除7001這個節點,所以源節點的id就是7001的節點ID
Source node #2:done //輸入done,回車,就會開始從7001 這個節點遷移16384個slot(沒有這麼多就遷移擁有的全部)到7002節點中去.

再看各個節點的狀態

redis-cli -c -p 7002 cluster nodes 
a2eee0ea546f2c3701b08981737c07938039857c 192.168.1.80:7001 master - 0 1463477349186 1 connected

7001 已經沒有分配slots了,可以從叢集中刪除了.

redis-trib.rb del-node 192.168.1.80:7002 a2eee0ea546f2c3701b08981737c07938039857c      
ps: 這個主節點被刪除之後,它之前擁有的從節點會自動成為其他主節點的從節點                       

五、原理

 Redis 叢集中內建了 16384 個雜湊槽,當需要在 Redis 叢集中放置一個 key-value 時,redis 先對 key 使用 crc16 演算法算出一個結果,然後把結果對 16384 求餘數,這樣每個 key 都會對應一個編號在 0-16383 之間的雜湊槽,redis 會根據節點數量大致均等的將雜湊槽對映到不同的節點。

六、cache叢集方案對比

  1. Twemproxy – Twitter
  2. Codis – 豌豆莢
  3. Redis Cluster – 官方

twemproxy

架構圖:
twemproxy架構

優點:

  • 開發簡單,對應用幾乎透明
  • 歷史悠久,成熟
    缺點:
  • 代理影響效能
  • lvs和twemproxy會有節點效能瓶頸
    • redis擴容非常麻煩
    • twitter內部已放棄使用該方案,新使用的架構未開源

Codis:

架構圖
codis架構圖

ZooKeeper:
    存放路由表和代理節點元資料
    分發Codis-Config的命令
Codis-Config :
    整合管理工具,有web介面
Codis-Proxy :
    無狀態代理,相容Redis協議
    對業務透明
Codis-Redis:
    基於2.8版本,二次開發
    加入slot支援和遷移命令

優點:
- 開發簡單,對應用幾乎透明
- 效能比Twemproxy好
- 有圖形化介面,擴容容易,運維方便
缺點:
- 代理依舊影響效能
- 元件過多,需要很多機器資源
- 修改了redis程式碼,導致和官方無法同步,新特性跟進緩慢
- 開發團隊準備主推基於redis改造的reborndb

Redis Cluster:

架構圖:
redis cluster

P2P模式,無中心化
把key分成16384個slot
每個例項負責一部分slot
客戶端請求若不在連線的例項,該例項會轉發給對應的例項。
通過Gossip協議同步節點資訊

優點:
- 元件all-in-box,部署簡單,節約機器資源
- 效能比proxy模式好
- 自動故障轉移、Slot遷移中資料可用
- 官方原生叢集方案,更新與支援有保障
缺點:
- 架構比較新,最佳實踐較少
- 多鍵操作支援有限(驅動可以曲線救國)
- 為了效能提升,客戶端需要快取路由表資訊
- 節點發現、reshard操作不夠自動化

七、總結

redis支援少量資料儲存,可以全部以in-momery方式支援高速訪問,同時支援資料落地的功能。
redis叢集可以支援儲存海量資料,支援分散式橫向拓展,資料一致性保證。