redis 集羣搭建詳細過程

準備工作

在 github 上下載 redis 源碼,編譯

./configure
make

LZ 下載的 redis 版本是 3.0.7
編譯成功後,在源碼的根目錄下的 src 目錄中,會生成對應的可執行文件

redis-server redis 服務器啓動程序
redis-cli redis客戶端程序
redis-trib.rb 這是一個ruby程序,可以用於創建集羣、檢查、刪除節點等
redis-sentinel 哨兵程序,能夠監控redis HA和主備主機

創建集羣

在 redis 官網也介紹了集羣的搭建方法 [https://redis.io/topics/cluster-tutorial]

LZ 共使用了四個虛擬機,用於創建集羣,每天虛擬機三個節點,分別是一個 RHEL,三個Ubuntu Server 16.04,IP地址分別如下:

192.168.192.166,以下簡稱166
192.168.192.132,以下簡稱132
192.168.192.133,以下簡稱133
192.168.192.134,以下簡稱134

創建節點

在 166 主機創建 config/clusters/ 目錄,再在這個目錄下創建 7001, 7002 和 7003 三個目錄,分別以目錄名稱作爲端口號(前提是你的機器上這些端口號沒有被佔用, netstat -pnl 查看端口號)

創建一個通用配置文件 redis-common.conf

daemonize yes
tcp-backlog 511
timeout 0
tcp-keepalive 0
loglevel debug  #開放最大日誌級別,能夠通過日誌信息查看更多細節
database 16
slave-serve-stale-data yes #redis在複製的時候也可訪問

#slave 只讀
slave-read-only yes

repl-disable-tcp-nodelay yes
slave-priority 100

#打開 aof
appendonly yes
appendfsync everysec #在不清楚的這個配置的情況,redis 推薦設置這個參數爲 everysec
no-appendfsync-on-rewrite yes #關閉aof rewite的時候對新的寫操作進行 fsync
auto-aof-rewrite-min-size 64mb

lua-time 5000

#打開redis集羣
cluster-enabled yes

#節點互聯超時時的閥值
cluster-node-timeout 15000
cluster-migration-barrier 1

#slow log
slowlog-log-slower-than 10000
slowlog-max-len 128
notify-keyspace-events ""  
hash-max-ziplist-entries 512  
hash-max-ziplist-value 64  
list-max-ziplist-entries 512  
list-max-ziplist-value 64  
set-max-intset-entries 512  
zset-max-ziplist-entries 128  
zset-max-ziplist-value 64  
activerehashing yes  
client-output-buffer-limit normal 0 0 0  
client-output-buffer-limit slave 256mb 64mb 60  
client-output-buffer-limit pubsub 32mb 8mb 60  
hz 10  
aof-rewrite-incremental-fsync yes

再根據不同的節點,爲每一個節點創建一個特殊的配置文件,比如 redis-7001.conf,並通過 include 包含通用配置

include redis-common.conf

port 7001
bind 192.168.192.166

logfile "" #日誌文件保存路徑+日誌文件名,建議方便的話,可以保存在對應的節點目錄下
dir "" #rdb, aof ,nodes.conf 文件的保存路徑

appendfilename "appendonly-7001.aof"

cluster-config-file "nodes-7001.conf" #這個配置文件是由redis自動創建的,裏面記錄的集羣節點的一些信息,比如master 節點,slave 節點的IP,端口號以及狀態(是否failed)

maxmemory 100m
maxmemory-policy allkeys-lru #內存耗盡時的淘汰策略
#remove any keys according to the LRU algorithm

auto-aof-rewrite-percentage 100

爲每一個虛擬機創建好三個節點之後,就開始啓用節點

啓動節點

166主機

redis-server redis-7001.conf
redis-server redis-7002.conf
redis-server redis-7003.conf

132主機

redis-server redis-7004.conf
redis-server redis-7005.conf
redis-server redis-7006.conf

133主機

redis-server redis-7007.conf
redis-server redis-7008.conf
redis-server redis-7009.conf

134主機

redis-server redis-7010.conf
redis-server redis-7011.conf
redis-server redis-7012.conf

節點啓動後,查看日誌信息,觀察是否均啓動成功

創建集羣

redis cluster 在設計的時候,就考慮到了去中心化,去中間件,也就是說,集羣中的每個節點都是平等的關係,都是對等的,每個節點都保存各自的數據和整個集羣的狀態。每個節點都和其他所有節點連接,而且這些連接保持活躍,這樣就保證了我們只需要連接集羣中的任意一個節點,就可以獲取到其他節點的數據。

Redis 集羣沒有並使用傳統的一致性哈希來分配數據,而是採用另外一種叫做哈希槽 (hash slot)的方式來分配的。redis cluster 默認分配了 16384 個slot,當我們set一個key 時,會用CRC16算法來取模得到所屬的slot,然後將這個key 分到哈希槽區間的節點上,具體算法就是:CRC16(key) % 16384。

Redis 集羣會把數據存在一個 master 節點,然後在這個 master 和其對應的salve 之間進行數據同步。當讀取數據時,也根據一致性哈希算法到對應的 master 節點獲取數據。只有當一個master 掛掉之後,纔會啓動一個對應的 salve 節點,充當 master 。

需要注意的是:必須要3個或以上的主節點,否則在創建集羣時會失敗,並且當存活的主節點數小於總節點數的一半時,整個集羣就無法提供服務了。

當所有的節點都創建好後,在 src 目錄中有一個文件 redis-trib.rb(前面介紹了這個文件),用這個工具創建集羣。

Usage: redis-trib <command> <options> <arguments ...>

  set-timeout     host:port milliseconds
  del-node        host:port node_id
  reshard         host:port
                  --from <arg>
                  --pipeline <arg>
                  --yes
                  --timeout <arg>
                  --slots <arg>
                  --to <arg>
  create          host1:port1 ... hostN:portN
                  --replicas <arg>
  help            (show this help)
  info            host:port
  check           host:port
  call            host:port command arg arg .. arg
  add-node        new_host:new_port existing_host:existing_port
                  --master-id <arg>
                  --slave
  rebalance       host:port
                  --weight <arg>
                  --threshold <arg>
                  --pipeline <arg>
                  --auto-weights
                  --simulate
                  --timeout <arg>
                  --use-empty-masters
  fix             host:port
                  --timeout <arg>
  import          host:port
                  --replace
                  --from <arg>
                  --copy

For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.

上面是這個工具的用法,該文件是使用 ruby 編寫的,首先在你的環境中需要安裝 ruby
RHEL 中安裝

yum install ruby

Ubuntu 中安裝

sudo apt-get install ruby

LZ因爲環境比較無語,主機無法連接網絡,所以都是使用的本地倉庫的形式,具體如何創建網絡倉庫,可以去找找資料,這裏不多說,Ubuntu 創建本地倉庫比較簡單,就是掛在一個鏡像,然後使用 apt-cdrom,在 source.list 文件中就會增加一個源,指向的就是掛在的鏡像目錄。

安裝好 ruby 之後,執行 redis-trib.rb 文件可能仍會報錯

`require`: no such file to load -- rubygems (LoadError)
`require`: no such file to load -- redis (LoadError)

這個是因爲你的環境中沒有安裝 rubygems 和 ruby redis (在沒網的環境中,手動下載依賴包簡直就是噩夢)

下載 rubygems: [https://rubygems.org/page/download]
ruby redis: [https://rubygems.org/gems/redis],這是一個ruby 的redis 客戶端

下載好 rubygems 後,執行

ruby setup.rb --help

能夠查看詳細的細節,安裝執行 gem

ruby setup.rb

安裝完成之後,即可安裝 ruby redis 客戶端了

gem install -l redis-3.2.1.gem

OK,環境配置好後,開始創建集羣

./redis-trib.rb create --replicas 2 192.168.192.166:7001 192.168.192.166:7002 192.168.192.166:7003 192.168.192.132:7004 192.168.192.132:7005 192.168.192.132:7006 192.168.192.133:7007 192.168.192.133:7008 192.168.192.133:7009 192.168.192.134:7010 192.168.192.134:7011 192.168.192.134:7012

創建12個節點,4個 master 節點,每一個 master 節點有 2 個 slave 節點。

如下圖所示表示成功
這裏寫圖片描述
這裏寫圖片描述

集羣操作

1. 查看節點信息

使用 redis-trib.rb info IP:PORT

./redis-trib.rb info  192.168.192.166:7001

這裏寫圖片描述

2. 檢查集羣狀態

使用 redis-trib.rb check IP:PORT

這裏寫圖片描述

3. 停止其中一個master,再啓動,觀察變化

當前集羣運行狀態是 OK 的

cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:12
cluster_size:4
cluster_current_epoch:17
cluster_my_epoch:1
cluster_stats_messages_sent:43924
cluster_stats_messages_received:11595

一共12個節點,有4個master節點,在 7001 的節點下,查看 node-7001.conf 這個文件(這個文件是 redis 自動生成的)

這裏寫圖片描述

這個文件記錄了集羣中所有相關的能夠到達的節點的信息,包括master的狀態(是否是failed)

我們來看一下,每一個master節點都有哪些slave,info replication 能夠清晰的查看slave 或者 master 的信息

master: 192.168.192.166 7003
ip:192.168.192.133,port:7007
ip:192.168.192.134,port:7012

master: 192.168.192.166 7002
ip:192.168.192.132,port:7005

master: 192.168.192.132 7004
ip:192.168.192.132,port:7006
ip:192.168.192.133,port:7009

master: 192.168.192.166 7001
ip:192.168.192.133,port:7008
ip:192.168.192.134,port:7011

這是當前我們的集羣分佈,上面的是 master,下面的兩個是該 master 的兩個 slave

現在我們來關閉其中一個 master,7004

redis-cli -h 192.168.192.132 -p 7004
shutdown

關閉之後再來查看 node-7001.conf 這個文件信息,此時發現,有一個 master 顯示的是 failed

這裏寫圖片描述

當 master failed 的時候,redis 會從它的從服務器中選一個作爲新的 master,然後另一個從服務器將作爲新的 master 的 slave,再來看集羣分佈

master: 192.168.192.132 7006
ip:192.168.192.133,port:7009

master: 192.168.192.166 7003
ip:192.168.192.133,port:7007
ip:192.168.192.134,port:7012

master: 192.168.192.166 7002
ip:192.168.192.132,port:7005

master: 192.168.192.166 7001
ip:192.168.192.133,port:7008
ip:192.168.192.134,port:7011

在沒有停止 7004 之前,7004 作爲 master,7006 和 7009 作爲它的 slave,在將 7004 停止之後,7006 成爲了新的 master,並且 7009 變成了它的 slave,當我們再次重新啓動 7004 時,redis 不會重新把它作爲 master,它將作爲新的 master 7006 的一個 slave

4. 集羣失敗

redis 集羣必須要有三個或以上的 master 節點,否則集羣將創建失敗,目前集羣的狀態時 ok,如果我們關閉 166 和 132 主機,查看集羣狀態爲 fail

這裏寫圖片描述

5. 添加新的 master 節點

在 132 主機上創建 8000 節點,在 133 主機上創建 8001 節點 (配置文件與其他節點的相同,只需要修改一下相應的文件保存路徑即可)

啓動節點

redis-server redis-8001.conf
redis-server redis-8000.conf

添加節點

./redis-trib.rb add-node 192.168.192.132:8000 192.168.192.133:7004

出現如下錯誤

[ERR] Node 192.168.192.132:8000 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.

這個節點之前添加了一次,沒有添加成功,導致節點非空,添加失敗,解決辦法:
1) 登陸數據庫,將數據進行刪除 flushdb
2) 將節點下的集羣配置文件刪除,即 node-8000.conf,redis 自動生成的文件
3) 刪除節點下的 aof , rdb 文件等本地備份文件

再次添加節點

>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Send CLUSTER MEET to node 192.168.192.132:8000 to make it join the cluster.
[OK] New node added correctly.

節點添加成功。查看集羣的狀態發現節點數成了13個

cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:13
cluster_size:4
cluster_current_epoch:24
cluster_my_epoch:0
cluster_stats_messages_sent:284
cluster_stats_messages_received:284

當前集羣的分佈如下所示

master: 192.168.192.132 7005
ip:192.168.192.134,port:7010
ip:192.168.192.166,port:7002

master: 192.168.192.132 7006
ip:192.168.192.133,port:7009
ip:192.168.192.132,port:7004

master: 192.168.192.166 7003
ip:192.168.192.134,port:7012
ip:192.168.192.133,port:7007

master: 192.168.192.132 8000

master: 192.168.192.166 7001
ip:192.168.192.133,port:7008
ip:192.168.192.134,port:7011

新添加的 8000 端口是 master 節點,它不包含任何數據,因爲沒有包含任何的 slot。新添加的都爲主節點,當集羣需要將某個節點升級爲新的主節點時,這個節點不會被選中。

爲新節點分配 slot

redis-trib.rb rehashed 192.168.192.132:8000

按照提示操作

#選擇要遷移的 slot 數量
How many slots do you want to move (from 1 to 16384)? 500
What is the receiving node ID? 81e71239d85d4112e87c5fe00d513f879c980118
#all 表示從所有的 master 重新分配
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
Ready to move 500 slots.
  Source nodes:
    M: 030197fec21c3192c0f8938ad276f8c8062c6410 192.168.192.166:7001
   slots:0-4095 (4096 slots) master
   2 additional replica(s)
    M: c6e30b67bc201f4f48bdf5fe9d88209505e2f0d9 192.168.192.132:7005
   slots:4096-8191 (4096 slots) master
   2 additional replica(s)
    M: 70d2ed1edd1035972927a7c8415ca9d0c941d21d 192.168.192.166:7003
   slots:8192-12287 (4096 slots) master
   2 additional replica(s)
    M: c63aac7105f9601915e65ef0d3ff45b0b3f0a7ec 192.168.192.132:7006
   slots:12288-16383 (4096 slots) master
   2 additional replica(s)
    M: 1a260ae8c08a9ee1b4d856e0fcf190c271590cf0 192.168.192.133:8001
   slots: (0 slots) master
   0 additional replica(s)
  Destination node:
    M: 81e71239d85d4112e87c5fe00d513f879c980118 192.168.192.132:8000
   slots: (0 slots) master
   0 additional replica(s)
  Resharding plan:
    Moving slot 0 from 030197fec21c3192c0f8938ad276f8c8062c6410
    ......
Do you want to proceed with the proposed reshard plan (yes/no)? yes
    Moving slot 0 from 192.168.192.166:7001 to 192.168.192.132:8000: 
    ......

6. 添加新的 slave 節點

節點添加與上面添加 master 的前面步驟相同
1. 創建節點目錄和節點配置文件,啓動節點
2. redis-trib.rb add-node new-ip:new-port exist_ip:exist_port
3. 這樣,添加上的節點爲 master 節點,然後使用 redis-cli 連接,輸入命令

cluster replicate node-id

即添加成功,node-id 可以通過查看命令 CLUSTER NODES查看,也可以直接查看節點的 node.conf 文件

NOTE:在線添加 slave 節點時,需要 dump 整個 master 進程,並傳遞到 slave,再由 slave 加載 rdb 文件到內存, rdb 傳輸過程中可能無法提供服務,整個過程需要消耗大量的I/O。

7. 刪除 master 節點

刪除節點之前,需要使用 reshard 移除該 master 的全部 slot,然後才能刪除節點,接收 slot 的節點必須是 master 節點

./redis-trib.rb reshard 192.168.192.134:8003

How many slots do you want to move (from 1 to 16384)? 500
What is the receiving node ID? c6023463d9f33e4c5ca72fdc85eb4c7d95b258a5
*** The specified node is not known or not a master, please retry.
What is the receiving node ID? 1a260ae8c08a9ee1b4d856e0fcf190c271590cf0
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:81e71239d85d4112e87c5fe00d513f879c980118
Source node #2:done

Ready to move 500 slots.
  Source nodes:
    M: 81e71239d85d4112e87c5fe00d513f879c980118 192.168.192.132:8000
   slots:0-124,4096-4220,8192-8316,12288-12412 (500 slots) master
   1 additional replica(s)
  Destination node:
    M: 1a260ae8c08a9ee1b4d856e0fcf190c271590cf0 192.168.192.133:8001
   slots: (0 slots) master
   0 additional replica(s)
  Resharding plan:
    Moving slot 0 from 81e71239d85d4112e87c5fe00d513f879c980118
    ......

移除所有的 slot 之後,刪除空 master 節點

redis-trib.rb del-node 192.168.192.132:8000 '81e71239d85d4112e87c5fe00d513f879c980118'

8. 刪除 slave 節點

#redis-trib.rb del-node ip:port 'node-id'
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章