此次在搞不定 Redis 集羣搭建!你來找我~~

  • Redis 集羣簡介node

    • 下載 & 安裝 Redislinux

    • 搭建 Redis 集羣面試

      • 手動方式搭建
      • 自動方式搭

Redis 集羣簡介

Redis Cluster 即 Redis 集羣,是 Redis 官方在 3.0 版本推出的一套分佈式存儲方案。徹底去中心化,由多個節點組成,全部節點彼此互聯。Redis 客戶端能夠直接鏈接任何一節點獲取集羣中的鍵值對,不須要中間代理,若是該節點不存在用戶所指定的鍵值,其內部會自動把客戶端重定向到鍵值所在的節點。redis

Redis 集羣是一個網狀結構,每一個節點都經過 TCP 鏈接跟其餘每一個節點鏈接。在一個有 N 個節點的集羣中,每一個節點都有 N-1 個流出的 TCP 鏈接,和 N-1 個流入的鏈接,這些 TCP 鏈接會永久保持。設計模式

file

Redis Cluster 同其餘分佈式存儲系統同樣,主要具有如下兩個功能:ruby

數據分區Redis 集羣會將用戶數據分散保存至各個節點中,突破單機 Redis 內存最大存儲容量。集羣引入了 哈希槽slot的概念,其搭建完成後會生 16384 個哈希槽slot,同時會根據節點的數量大體均等的將 16384 個哈希槽映射到不一樣的節點上。當用戶存儲key-value時,集羣會先對key進行 CRC16 校驗而後對 16384 取模來決定key-value放置哪一個槽,從而實現自動分割數據到不一樣的節點上。服務器

數據冗餘Redis 集羣支持主從複製和故障恢復。集羣使用了主從複製模型,每一個主節點master應至少有一個從節點slave。假設某個主節點故障,其全部子節點會廣播一個數據包給集羣裏的其餘主節點來請求選票,一旦某個從節點收到了大多數主節點的迴應,那麼它就贏得了選舉,被推選爲主節點,負責處理以前舊的主節點負責的哈希槽。分佈式

關於 Redis Cluster 詳細介紹以及實現原理請參見 Redis Cluster 教程 和 Redis Cluster 規範,在此再也不贅述。

下載 & 安裝 Redis

實驗環境信息 Linux 版本:CentOS Linux release 7.4.1708 Redis 版本:5.0.3

先在服務器或虛擬機中安裝一個單機 Redis,若是已安裝能夠跳過本節,未安裝過的正好學習下。ide

進入 Redis 待安裝目錄。工具

Copycd /usr/local

下載、解壓 Redis 源代碼壓縮包。

Copywget http://download.redis.io/releases/redis-5.0.3.tar.gz
tar -zxvf redis-5.0.3.tar.gz

而後進入解壓後的目錄並使用 make 命令執行編譯安裝 Redis。

Copycd redis-5.0.3
make && make install

不要高興,由於你極有可能會遇到由於 GCC 編譯器未安裝致使編譯失敗的狀況。不要着急,請順序執行以下命令。

Copyyum -y install gcc
make distclean
make && make install
Redis 基於 C 語言開發,故編譯源碼須要 GCC(Linux下的一個編譯器,這裏須要用來編譯`.c`文件)的支持。如機器上未安裝須要先執行命令`yum -y install gcc`安裝 GCC 編譯工具,而後`make distclean`清除以前生成的文件,最後`make && make install`從新編譯安裝。

最終出現相似下文輸出則表示 Redis 安裝成功。

Copy......
Hint: It's a good idea to run 'make test' ;)

    INSTALL install
    INSTALL install
    INSTALL install
    INSTALL install
    INSTALL install
make[1]: 離開目錄「/usr/local/redis-5.0.3/src」

若是源碼編譯無誤且執行結果正確,make install命令會將程序安裝至系統預設的可執行文件存放路徑,通常是/usr/local/bin目錄,能夠經過以下終端輸出確認。固然,也可使用make install PREFIX=命令安裝到指定路徑。

Copy[root@localhost bin]# cd /usr/local/bin
[root@localhost bin]# ls -l
總用量 32672
-rwxr-xr-x. 1 root root 4367328 3月   6 06:11 redis-benchmark
-rwxr-xr-x. 1 root root 8092024 3月   6 06:11 redis-check-aof
-rwxr-xr-x. 1 root root 8092024 3月   6 06:11 redis-check-rdb
-rwxr-xr-x. 1 root root 4802696 3月   6 06:11 redis-cli
lrwxrwxrwx. 1 root root      12 3月   6 06:11 redis-sentinel -  redis-server
-rwxr-xr-x. 1 root root 8092024 3月   6 06:11 redis-server

至此,單機 Redis 安裝完成。

搭建 Redis 集羣

進入正題。

依據 Redis Cluster 內部故障轉移實現原理,Redis 集羣至少須要 3 個主節點,而每一個主節點至少有 1 從節點,所以搭建一個集羣至少包含 6 個節點,三主三從,而且分別部署在不一樣機器上。

條件有限,測試環境下咱們只能在一臺機器上建立一個僞集羣,經過不一樣的 TCP 端口啓動多個 Redis 實例,組成集羣。

目前 Redis Cluster 的搭建有兩種方式:

  1. 手動方式搭建,即手動執行 cluster 命令,一步步完成搭建流程。
  2. 自動方式搭建,即便用官方提供的集羣管理工具快速搭建。

兩種方式原理同樣,自動搭建方式只是將手動搭建方式中須要執行的 Redis 命令封裝到了可執行程序。生產環境下推薦使用第二種方式,簡單快捷,不易出錯。不過本文實戰演示兩種方式都會說起。

手動方式搭建

啓動節點

搭建集羣的第一步就是要先把參與搭建集羣的每一個節點啓動起來。

因爲咱們這是在一臺機器上模擬多個節點,能夠預先規劃下各個節點的屬性:

節點編號 IP 地址 TCP 端口 節點類型 從節點 啓動配置
A 127.0.0.1 7001 D /usr/local/redis-cluster/7001/redis.conf
B 127.0.0.1 7002 E /usr/local/redis-cluster/7002/redis.conf
C 127.0.0.1 7003 F /usr/local/redis-cluster/7003/redis.conf
D 127.0.0.1 8001 / /usr/local/redis-cluster/8001/redis.conf
E 127.0.0.1 8002 / /usr/local/redis-cluster/8002/redis.conf
F 127.0.0.1 8003 / /usr/local/redis-cluster/8003/redis.conf

根據上述規劃,能夠先經過以下命令建立各個節點啓動配置文件的存放目錄。

Copymkdir /usr/local/redis-cluster
cd redis-cluster
mkdir -p 7001 7002 7003 8001 8002 8003

順序執行以下行命令,進入 Redis 源碼包目錄並將默認配置文件redis.conf分別複製到六個節點配置存放目錄中,做爲各自節點啓動配置文件。

Copycd /usr/local/redis-5.0.3
cp redis.conf /usr/local/redis-cluster/7001
cp redis.conf /usr/local/redis-cluster/7002
cp redis.conf /usr/local/redis-cluster/7003
cp redis.conf /usr/local/redis-cluster/8001
cp redis.conf /usr/local/redis-cluster/8002
cp redis.conf /usr/local/redis-cluster/8003

接下來須要分別修改每一個節點的配置文件。下面貼的是節點 A 的配置文件/usr/local/redis-cluster/7001/redis.conf中啓用或修改的一些必要參數。其餘節點 B、C、D、E、F 參照修改,注意把涉及端口的地方修改爲各自節點預先規劃的便可。

Copybind 192.168.83.128                    # 設置當前節點主機地址
port 7001                              # 設置客戶端鏈接監聽端口
pidfile /var/run/redis_7001.pid        # 設置 Redis 實例 pid 文件
daemonize yes                          # 以守護進程運行 Redis 實例
cluster-enabled yes                    # 啓用集羣模式
cluster-node-timeout 15000             # 設置當前節點鏈接超時毫秒數
cluster-config-file nodes-7001.conf    # 設置當前節點集羣配置文件路徑

完成上述工做就能夠經過以下幾組命令啓動待搭建集羣中的 6 個節點了。

Copy/usr/local/bin/redis-server /usr/local/redis-cluster/7001/redis.conf
/usr/local/bin/redis-server /usr/local/redis-cluster/7002/redis.conf
/usr/local/bin/redis-server /usr/local/redis-cluster/7003/redis.conf
/usr/local/bin/redis-server /usr/local/redis-cluster/8001/redis.conf
/usr/local/bin/redis-server /usr/local/redis-cluster/8002/redis.conf
/usr/local/bin/redis-server /usr/local/redis-cluster/8003/redis.conf

最後經過ps -ef|grep redis命令確認各個節點服務是否已經正常運行。

Copy[root@localhost bin]# ps -ef|grep redis
root       5613      1  0 04:25 ?        00:00:00 /usr/local/bin/redis-server 127.0.0.1:7001 [cluster]
root       5650      1  0 04:26 ?        00:00:00 /usr/local/bin/redis-server 127.0.0.1:7002 [cluster]
root       5661      1  0 04:26 ?        00:00:00 /usr/local/bin/redis-server 127.0.0.1:7003 [cluster]
root       5672      1  0 04:27 ?        00:00:00 /usr/local/bin/redis-server 127.0.0.1:8001 [cluster]
root       5681      1  0 04:27 ?        00:00:00 /usr/local/bin/redis-server 127.0.0.1:8002 [cluster]
root       5690      1  0 04:27 ?        00:00:00 /usr/local/bin/redis-server 127.0.0.1:8003 [cluster]
root       5731   1311  0 04:28 pts/0    00:00:00 grep --color=auto redis

如上輸出能夠看出上面規劃的 6 個節點都成功啓動。

節點握手

雖然上面 6 個節點都啓用了羣集支持,但默認狀況下它們是不相互信任或者說沒有聯繫的。節點握手就是在各個節點之間建立連接(每一個節點與其餘節點相連),造成一個完整的網格,即集羣。

節點握手的命令以下:

Copycluster meet ip port

但爲了建立羣集,不須要發送造成完整網格所需的全部 cluster meet 命令。只要能發送足夠的cluster meet消息,可讓每一個節點均可以經過一系列已知節點到達每一個其餘節點,缺失的連接將被自動建立。

例如,若是咱們經過cluster meet將節點 A 與節點 B 鏈接起來,並將 B 與 C 鏈接起來,則 A 和 C 會本身找到握手方式並建立連接。

咱們的建立的 6 個節點能夠經過 redis-cli 鏈接到 A 節點執行以下五組命令完成握手,生產環境須要將 IP 127.0.0.1替換成外網 IP。

Copycluster meet 127.0.0.1 7002
cluster meet 127.0.0.1 7003
cluster meet 127.0.0.1 8001
cluster meet 127.0.0.1 8002
cluster meet 127.0.0.1 8003

如上述命令正常執行輸出結果以下。

Copy[root@localhost bin]# /usr/local/bin/redis-cli -p 7001
127.0.0.1:7001> cluster meet 127.0.0.1 7002
OK
127.0.0.1:7001> cluster meet 127.0.0.1 7003
OK
127.0.0.1:7001> cluster meet 127.0.0.1 8001
OK
127.0.0.1:7001> cluster meet 127.0.0.1 8002
OK
127.0.0.1:7001> cluster meet 127.0.0.1 8003
OK

接下來能夠經過 cluster nodes 命令查看節點之間 的連接狀態。我隨機找了兩個節點 B 和 F 測試,輸出結果以下所示。

Copy[root@localhost /]# /usr/local/bin/redis-cli -p 7002 cluster nodes
61e8c4ed8d1ff2a765a4dd2c3d300d8121d26e12 127.0.0.1:7001@17001 master - 0 1552220691885 4 connected
a8a41694f22977fda78863bdfb3fc03dd1fab1bd 127.0.0.1:8002@18002 master - 0 1552220691000 5 connected
51987c4b5530c81f2845bb9d521daf6d3dce3659 127.0.0.1:8001@18001 master - 0 1552220690878 3 connected
1b4b3741945d7fed472a1324aaaa6acaa1843ccb 127.0.0.1:7002@17002 myself,master - 0 1552220690000 1 connected
19147f56e679767bcebb8653262ff7f56ca072a8 127.0.0.1:7003@17003 master - 0 1552220691000 2 connected
ed6fd72e61b747af3705b210c7164bc68739303e 127.0.0.1:8003@18003 master - 0 1552220690000 0 connected
[root@localhost /]# /usr/local/bin/redis-cli -p 8002 cluster nodes
1b4b3741945d7fed472a1324aaaa6acaa1843ccb 127.0.0.1:7002@17002 master - 0 1552220700255 1 connected
ed6fd72e61b747af3705b210c7164bc68739303e 127.0.0.1:8003@18003 master - 0 1552220703281 0 connected
19147f56e679767bcebb8653262ff7f56ca072a8 127.0.0.1:7003@17003 master - 0 1552220700000 2 connected
a8a41694f22977fda78863bdfb3fc03dd1fab1bd 127.0.0.1:8002@18002 myself,master - 0 1552220701000 5 connected
61e8c4ed8d1ff2a765a4dd2c3d300d8121d26e12 127.0.0.1:7001@17001 master - 0 1552220702275 4 connected
51987c4b5530c81f2845bb9d521daf6d3dce3659 127.0.0.1:8001@18001 master - 0 1552220701265 3 connected

能夠看到,節點 B 和節點 F 都已經分別和其餘 5 個節點創建連接。

至此,節點握手完成。

分配槽位

此時 Redis 集羣還並無處於上線狀態,能夠在任意一節點上執行 cluster info 命令來查看目前集羣的運行狀態。

Copy[root@localhost ~]# /usr/local/bin/redis-cli -p 7001 cluster info
cluster_state:fail
......

上面輸出cluster_state:fail表示當前集羣處於下線狀態。由於只有給集羣中全部主節點分配好槽位(即哈希槽slot,本文第一小節有說起)集羣才能上線。

分配槽位的命令以下:

Copycluster addslots slot [slot ...]

根據預先規劃,這一步須要使用 cluster addslots 命令手動將 16384 個哈希槽大體均等分配給主節點 A、B、C。

Copy/usr/local/bin/redis-cli -p 7001 cluster addslots {0..5461}
/usr/local/bin/redis-cli -p 7002 cluster addslots {5462..10922}
/usr/local/bin/redis-cli -p 7003 cluster addslots {10923..16383}

上面三組命令執行完畢,能夠再次查看目前集羣的一些運行參數。

Copy[root@localhost ~]# /usr/local/bin/redis-cli -p 7001 cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:5
cluster_my_epoch:4
cluster_stats_messages_ping_sent:11413
cluster_stats_messages_pong_sent:10509
cluster_stats_messages_meet_sent:11
cluster_stats_messages_sent:21933
cluster_stats_messages_ping_received:10509
cluster_stats_messages_pong_received:10535
cluster_stats_messages_received:21044

如上輸出cluster_state:ok證實 Redis 集羣成功上線。

主從複製

Redis 集羣成功上線,不過尚未給主節點指定從節點,此時若是有一個節點故障,那麼整個集羣也就掛了,也就沒法實現高可用。

集羣中須要使用 cluster replicate 命令手動給從節點配置主節點。

集羣複製命令以下:

Copycluster replicate node-id

集羣中各個節點的node-id能夠用cluster nodes命令查看,以下輸出1b4b3741945d7fed472a1324aaaa6acaa1843ccb便是主節點 B 的node-id

Copy[root@localhost /]# /usr/local/bin/redis-cli -p 8002 cluster nodes
1b4b3741945d7fed472a1324aaaa6acaa1843ccb 127.0.0.1:7002@17002 master - 0 1552220700255 1 connected
ed6fd72e61b747af3705b210c7164bc68739303e 127.0.0.1:8003@18003 master - 0 1552220703281 0 connected
19147f56e679767bcebb8653262ff7f56ca072a8 127.0.0.1:7003@17003 master - 0 1552220700000 2 connected
a8a41694f22977fda78863bdfb3fc03dd1fab1bd 127.0.0.1:8002@18002 myself,master - 0 1552220701000 5 connected
61e8c4ed8d1ff2a765a4dd2c3d300d8121d26e12 127.0.0.1:7001@17001 master - 0 1552220702275 4 connected
51987c4b5530c81f2845bb9d521daf6d3dce3659 127.0.0.1:8001@18001 master - 0 1552220701265 3 connected

根據預先規劃,A主D從;B主E從;C主F從。執行以下三組命令分別爲從節點 D、E、F 指定其主節點,使羣集能夠自動完成主從複製。

Copy/usr/local/bin/redis-cli -p 8001 cluster replicate 61e8c4ed8d1ff2a765a4dd2c3d300d8121d26e12
/usr/local/bin/redis-cli -p 8002 cluster replicate 1b4b3741945d7fed472a1324aaaa6acaa1843ccb
/usr/local/bin/redis-cli -p 8003 cluster replicate 19147f56e679767bcebb8653262ff7f56ca072a8

命令執行成功後,咱們便算以手動方式成功搭建了一個 Redis 集羣。

最後,再來查看一下集羣中的節點信息。

Copy[root@localhost ~]# /usr/local/bin/redis-cli -p 8002 cluster nodes
1b4b3741945d7fed472a1324aaaa6acaa1843ccb 127.0.0.1:7002@17002 master - 0 1552233328337 1 connected 5462-10922
ed6fd72e61b747af3705b210c7164bc68739303e 127.0.0.1:8003@18003 slave 19147f56e679767bcebb8653262ff7f56ca072a8 0 1552233327000 2 connected
19147f56e679767bcebb8653262ff7f56ca072a8 127.0.0.1:7003@17003 master - 0 1552233325000 2 connected 10923-16383
a8a41694f22977fda78863bdfb3fc03dd1fab1bd 127.0.0.1:8002@18002 myself,slave 1b4b3741945d7fed472a1324aaaa6acaa1843ccb 0 1552233327000 5 connected
61e8c4ed8d1ff2a765a4dd2c3d300d8121d26e12 127.0.0.1:7001@17001 master - 0 1552233327327 4 connected 0-5461
51987c4b5530c81f2845bb9d521daf6d3dce3659 127.0.0.1:8001@18001 slave 61e8c4ed8d1ff2a765a4dd2c3d300d8121d26e12 0 1552233326320 4 connected

自動方式搭建

Redis 3.0 版本以後官方發佈了一個集羣管理工具 redis-trib.rb,集成在 Redis 源碼包的src目錄下。其封裝了 Redis 提供的集羣命令,使用簡單、便捷。

不過 redis-trib.rb 是 Redis 做者使用 Ruby 語言開發的,故使用該工具以前還須要先在機器上安裝 Ruby 環境。後面做者可能意識到這個問題,Redis 5.0 版本開始便把這個工具集成到 redis-cli 中,以--cluster參數提供使用,其中create命令能夠用來建立集羣。

啓動節點

使用集羣管理工具搭建集羣以前,也是須要先把各個節點啓動起來的。節點的啓動方式請參見本文「手動方式建立」-「啓動節點」一節,此處再也不贅述。

集羣管理工具搭建

若是您安裝的 Redis 是 3.x 和 4.x 的版本可使用 redis-trib.rb 搭建,不過以前須要安裝 Ruby 環境。

先使用 yum 安裝 Ruby 環境以及其餘依賴項。

Copyyum -y install ruby ruby-devel rubygems rpm-build

確認安裝版本。

Copy[root@localhost redis-cluster]# ruby -v
ruby 2.0.0p648 (2015-12-16) [x86_64-linux]

再使用 redis-trib.rb 腳本搭建集羣,具體命令以下所示。

Copy/usr/local/redis-5.0.3/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:8001 127.0.0.1:8002 127.0.0.1:8003

不過,本文實驗環境使用的 Redis 版本是 5.0.3,因此我能夠直接使用redis-cli --cluster create命令搭建,具體命令以下所示。

Copy/usr/local/bin/redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:8001 127.0.0.1:8002 127.0.0.1:8003 --cluster-replicas 1

主節點在前,從節點在後。其中--cluster-replicas參數用來指定一個主節點帶有的從節點個數,如上--cluster-replicas 1即表示 1 個主節點有 1 個從節點。

命令執行成功會有相似以下輸出。

Copy[root@localhost bin]# redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:8001 127.0.0.1:8002 127.0.0.1:8003 --cluster-replicas 1
 >> Performing hash slots allocation on 6 nodes...
Master[0] -  Slots 0 - 5460
Master[1] -  Slots 5461 - 10922
Master[2] -  Slots 10923 - 16383
Adding replica 127.0.0.1:8001 to 127.0.0.1:7001
Adding replica 127.0.0.1:8002 to 127.0.0.1:7002
Adding replica 127.0.0.1:8003 to 127.0.0.1:7003
 >> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 32f9819fc7d561bfa2b7189182200e86d9901b8a 127.0.0.1:7001
   slots:[0-5460] (5461 slots) master
M: cca0fbfa374bc175d481e68ee9ed13b65453e967 127.0.0.1:7002
   slots:[5461-10922] (5462 slots) master
M: 964cfa1c2dcfe36b6d3c63637f0d57ccb568354e 127.0.0.1:7003
   slots:[10923-16383] (5461 slots) master
S: 1b47b9e6e7a79523579b8d2ddcd5e708583ed317 127.0.0.1:8001
   replicates 32f9819fc7d561bfa2b7189182200e86d9901b8a
S: aba9330f3e70f26a8af4ced1b672fbcc7bc62d78 127.0.0.1:8002
   replicates cca0fbfa374bc175d481e68ee9ed13b65453e967
S: 254db0830cd764e075aa793144572d5fa3a398f0 127.0.0.1:8003
   replicates 964cfa1c2dcfe36b6d3c63637f0d57ccb568354e
Can I set the above configuration? (type 'yes' to accept): yes
 >> Nodes configuration updated
 >> Assign a different config epoch to each node
 >> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
...
 >> Performing Cluster Check (using node 127.0.0.1:7001)
M: 32f9819fc7d561bfa2b7189182200e86d9901b8a 127.0.0.1:7001
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: aba9330f3e70f26a8af4ced1b672fbcc7bc62d78 127.0.0.1:8002
   slots: (0 slots) slave
   replicates cca0fbfa374bc175d481e68ee9ed13b65453e967
S: 1b47b9e6e7a79523579b8d2ddcd5e708583ed317 127.0.0.1:8001
   slots: (0 slots) slave
   replicates 32f9819fc7d561bfa2b7189182200e86d9901b8a
S: 254db0830cd764e075aa793144572d5fa3a398f0 127.0.0.1:8003
   slots: (0 slots) slave
   replicates 964cfa1c2dcfe36b6d3c63637f0d57ccb568354e
M: cca0fbfa374bc175d481e68ee9ed13b65453e967 127.0.0.1:7002
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
M: 964cfa1c2dcfe36b6d3c63637f0d57ccb568354e 127.0.0.1:7003
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
 >> Check for open slots...
 >> Check slots coverage...
[OK] All 16384 slots covered.

OK,搭建完成!一條命令搞定。

歡迎關注公衆號 【碼農開花】一塊兒學習成長 我會一直分享Java乾貨,也會分享免費的學習資料課程和麪試寶典 回覆:【計算機】【設計模式】有驚喜哦

相關文章
相關標籤/搜索