redis集羣搭建與管理

集羣簡介:
Redis 集羣是一個能夠在多個 Redis 節點之間進行數據共享的設施(installation)。
Redis 集羣不支持那些須要同時處理多個鍵的 Redis 命令, 由於執行這些命令須要在多個 Redis 節點之間移動數據, 而且在高負載的狀況下, 這些命令將下降 Redis 集羣的性能, 並致使不可預測的行爲。
Redis 集羣經過分區(partition)來提供必定程度的可用性(availability): 即便集羣中有一部分節點失效或者沒法進行通信, 集羣也能夠繼續處理命令請求。
Redis 集羣提供瞭如下兩個好處:
將數據自動切分(split)到多個節點的能力。
當集羣中的一部分節點失效或者沒法進行通信時, 仍然能夠繼續處理命令請求的能力。
 
redis集羣數據共享:
Redis 集羣使用數據分片(sharding)而非一致性哈希(consistency hashing)來實現: 一個 Redis 集羣包含 16384 個哈希槽(hash slot), 數據庫中的每一個鍵都屬於這 16384 個哈希槽的其中一個, 集羣使用公式 CRC16(key) % 16384 來計算鍵 key 屬於哪一個槽, 其中 CRC16(key) 語句用於計算鍵 key 的 CRC16 校驗和 。
集羣中的每一個節點負責處理一部分哈希槽。 舉個例子, 一個集羣能夠有三個哈希槽, 其中:
節點 A 負責處理 0 號至 5500 號哈希槽。
節點 B 負責處理 5501 號至 11000 號哈希槽。
節點 C 負責處理 11001 號至 16384 號哈希槽。
這種將哈希槽分佈到不一樣節點的作法使得用戶能夠很容易地向集羣中添加或者刪除節點。 好比說:
若是用戶將新節點 D 添加到集羣中, 那麼集羣只須要將節點 A 、B 、 C 中的某些槽移動到節點 D 就能夠了。
與此相似, 若是用戶要從集羣中移除節點 A , 那麼集羣只須要將節點 A 中的全部哈希槽移動到節點 B 和節點 C , 而後再移除空白(不包含任何哈希槽)的節點 A 就能夠了。
由於將一個哈希槽從一個節點移動到另外一個節點不會形成節點阻塞, 因此不管是添加新節點仍是移除已存在節點, 又或者改變某個節點包含的哈希槽數量, 都不會形成集羣下線。
 
redis集羣中的主從複製:
爲了使得集羣在一部分節點下線或者沒法與集羣的大多數(majority)節點進行通信的狀況下, 仍然能夠正常運做, Redis 集羣對節點使用了主從複製功能: 集羣中的每一個節點都有 1 個至 N 個複製品(replica), 其中一個複製品爲主節點(master), 而其他的 N-1 個複製品爲從節點(slave)。
在以前列舉的節點 A 、B 、C 的例子中, 若是節點 B 下線了, 那麼集羣將沒法正常運行, 由於集羣找不到節點來處理 5501 號至 11000 號的哈希槽。
另外一方面, 假如在建立集羣的時候(或者至少在節點 B 下線以前), 咱們爲主節點 B 添加了從節點 B1 , 那麼當主節點 B 下線的時候, 集羣就會將 B1 設置爲新的主節點, 並讓它代替下線的主節點 B , 繼續處理 5501 號至 11000 號的哈希槽, 這樣集羣就不會由於主節點 B 的下線而沒法正常運做了。
不過若是節點 B 和 B1 都下線的話, Redis 集羣仍是會中止運做。
 
redis集羣的數據一致性:
Redis 集羣不保證數據的強一致性(strong consistency): 在特定條件下, Redis 集羣可能會丟失已經被執行過的寫命令。
使用異步複製(asynchronous replication)是 Redis 集羣可能會丟失寫命令的其中一個緣由。 考慮如下這個寫命令的例子:
客戶端向主節點 B 發送一條寫命令。
主節點 B 執行寫命令,並向客戶端返回命令回覆。
主節點 B 將剛剛執行的寫命令複製給它的從節點 B1 、 B2 和 B3 。
如你所見, 主節點對命令的複製工做發生在返回命令回覆以後, 由於若是每次處理命令請求都須要等待複製操做完成的話, 那麼主節點處理命令請求的速度將極大地下降 —— 咱們必須在性能和一致性之間作出權衡。
Redis 集羣另一種可能會丟失命令的狀況是, 集羣出現網絡分裂(network partition), 而且一個客戶端與至少包括一個主節點在內的少數(minority)實例被孤立。
舉個例子, 假設集羣包含 A 、 B 、 C 、 A1 、 B1 、 C1 六個節點, 其中 A 、B 、C 爲主節點, 而 A1 、B1 、C1 分別爲三個主節點的從節點, 另外還有一個客戶端 Z1 。
假設集羣中發生網絡分裂, 那麼集羣可能會分裂爲兩方, 大多數(majority)的一方包含節點 A 、C 、A1 、B1 和 C1 , 而少數(minority)的一方則包含節點 B 和客戶端 Z1 。
在網絡分裂期間, 主節點 B 仍然會接受 Z1 發送的寫命令:
若是網絡分裂出現的時間很短, 那麼集羣會繼續正常運行;
可是, 若是網絡分裂出現的時間足夠長, 使得大多數一方將從節點 B1 設置爲新的主節點, 並使用 B1 來代替原來的主節點 B , 那麼 Z1 發送給主節點 B 的寫命令將丟失。
注意, 在網絡分裂出現期間, 客戶端 Z1 能夠向主節點 B 發送寫命令的最大時間是有限制的, 這一時間限制稱爲節點超時時間(node timeout), 是 Redis 集羣的一個重要的配置選項:
對於大多數一方來講, 若是一個主節點未能在節點超時時間所設定的時限內從新聯繫上集羣, 那麼集羣會將這個主節點視爲下線, 並使用從節點來代替這個主節點繼續工做。
對於少數一方, 若是一個主節點未能在節點超時時間所設定的時限內從新聯繫上集羣, 那麼它將中止處理寫命令, 並向客戶端報告錯誤。
下面開始集羣的搭建和管理:首先介紹一下咱們的實驗環境
測試環境兩臺:
server1:172.16.16.34
server2:172.16.16.35
redis版本:redis3.2

搭建環境:redis集羣,server1有7001,7002,7003三主,server2有7001,7002,7003三從,總共六個節點。這樣作是爲了保證redis的集羣的高可用。redis的複製也是採用異步複製的方式。node

1,安裝redis
cd /home/maxiangqian
tar xzf redis-3.2.8.tar.gz
cd redis-3.2.8
yum install gcc
make
 

2:建立redis目錄文件夾redis

在server1和server2上都建立相應的文件夾:
mkdir /home/redis7001/data
mkdir -p /home/redis7001/data /home/redis7001/log /home/redis7001/tmp
mkdir -p /home/redis7002/data /home/redis7002/log /home/redis7002/tmp
mkdir -p /home/redis7003/data /home/redis7003/log /home/redis7003/tmp

3:爲server1和server2的三個節點分別配置配置文件mongodb

以一個配置文件爲例:
port 7001
timeout 300
 
daemonize yes
pidfile "/home/redis7001/tmp/redis_7001.pid"
 
loglevel notice
logfile "/home/redis7001/log/redis_7001.log"
 
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename "dump.rdb"
dir "/home/redis7001/data"
 
slave-serve-stale-data yes
#slave-read-only yes # yes開啓從庫只讀
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
 
appendonly yes
#appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
 
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
 
requirepass "maxiangqianredis"
masterauth "maxiangqianredis"
 
#cluster
cluster-enabled yes
cluster-config-file /home/redis7001/nodes7001.conf
cluster-node-timeout 5000

上面是redis7001的配置文件內容數據庫

而後啓動7001的redis:
redis-server /home/redis7001/redis7001.conf

咱們看一下啓動日誌:ruby

1574:M 03 May 16:22:53.444 * No cluster configuration found, I'm 363ecec54c92c2548dcab016146bdb4c104e5e84

 

每一個實例都會爲本身生成一個惟一的ID,用來識別集羣中的惟一身份。
而後使用一樣的方法啓動其他五個實例
server1 7001
server1 7002
server1 7003
server2 7001
server2 7002
server2 7003

OK,如今已經有六個已經啓動的redis實例了。咱們下一步開始作集羣網絡

 4:開始建立集羣
redis-trib.rb create --replicas 1 10.103.16.34:7001 10.103.16.34:7002 10.103.16.34:7003 10.103.16.35:7001 10.103.16.35:7002 10.103.16.35:7003

執行報錯:app

/usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- redis (LoadError)
from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
from /home/maxiangqian/redis-3.2.8/src/redis-trib.rb:25

咱們須要安裝如下幾個包:less

yum -y install zlib ruby rubygems
gem install redis

而後從新啓動建立集羣的操做:異步

[root@localhost redis7003]# redis-trib.rb create --replicas 1 10.103.16.34:7001 10.103.16.34:7002 10.103.16.34:7003 10.103.16.35:7001 10.103.16.35:7002 10.103.16.35:7003
>>> Creating cluster
[ERR] Sorry, can't connect to node 10.103.16.34:7001

又報錯了我擦。async

網上各類搜資料諮詢,最好仍是發現不是什麼版本問題,是由於個人配置文件里加瞭如下兩行配置:
requirepass "maxiangqianredis"
masterauth "maxiangqianredis"

羣集認證是要配置完成再添加的,並且兩個參數配置必須同樣,咱們如今暫時不配置認證模式:

[root@localhost redis7003]# redis-trib.rb create --replicas 1 10.103.16.34:7001 10.103.16.34:7002 10.103.16.34:7003 10.103.16.35:7001 10.103.16.35:7002 10.103.16.35:7003
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
10.103.16.35:7001
10.103.16.34:7001
10.103.16.35:7002
Adding replica 10.103.16.34:7002 to 10.103.16.35:7001
Adding replica 10.103.16.35:7003 to 10.103.16.34:7001
Adding replica 10.103.16.34:7003 to 10.103.16.35:7002
M: 363ecec54c92c2548dcab016146bdb4c104e5e84 10.103.16.34:7001
slots:5461-10922 (5462 slots) master
S: 93a0e8d405959480fcbd310a5d15a92346c69d43 10.103.16.34:7002
replicates d015a22abc57c021f568973f4f1c03c7a5c7b772
S: 78f77749f9f9a5f0d7c99427e0311912a3fa04e7 10.103.16.34:7003
replicates 89147e5837e378b69233dd2b8290267975719bc4
M: d015a22abc57c021f568973f4f1c03c7a5c7b772 10.103.16.35:7001
slots:0-5460 (5461 slots) master
M: 89147e5837e378b69233dd2b8290267975719bc4 10.103.16.35:7002
slots:10923-16383 (5461 slots) master
S: ce9d635236567ccde4c864f78863fa0a4b26f25a 10.103.16.35:7003
replicates 363ecec54c92c2548dcab016146bdb4c104e5e84
Can I set the above configuration? (type 'yes' to accept):

OK,已經提示成功了,咱們直接選擇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 10.103.16.34:7001)
M: 363ecec54c92c2548dcab016146bdb4c104e5e84 10.103.16.34:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 78f77749f9f9a5f0d7c99427e0311912a3fa04e7 10.103.16.34:7003
slots: (0 slots) slave
replicates 89147e5837e378b69233dd2b8290267975719bc4
M: d015a22abc57c021f568973f4f1c03c7a5c7b772 10.103.16.35:7001
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: 89147e5837e378b69233dd2b8290267975719bc4 10.103.16.35:7002
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: ce9d635236567ccde4c864f78863fa0a4b26f25a 10.103.16.35:7003
slots: (0 slots) slave
replicates 363ecec54c92c2548dcab016146bdb4c104e5e84
S: 93a0e8d405959480fcbd310a5d15a92346c69d43 10.103.16.34:7002
slots: (0 slots) slave
replicates d015a22abc57c021f568973f4f1c03c7a5c7b772
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

這樣羣集就設置成功了。

查看一下集羣的狀態,測試一下:
在10.103.16.34:7001建立name測試字符串,而後驗證
[root@mxqmongodb2 sa]# redis-cli -c -p 7001
127.0.0.1:7001> get name
-> Redirected to slot [5798] located at 10.103.16.34:7001
"txt"
10.103.16.34:7001> exit
[root@mxqmongodb2 sa]# redis-cli -c -p 7002
127.0.0.1:7002> get name
-> Redirected to slot [5798] located at 10.103.16.34:7001
"txt"
10.103.16.34:7001> exit
[root@mxqmongodb2 sa]# redis-cli -c -p 7003
127.0.0.1:7003> get name
-> Redirected to slot [5798] located at 10.103.16.34:7001
"txt"

5:咱們接下來查看一下集羣的基本信息:

[root@localhost redis7003]# redis-cli -p 7001 cluster nodes
78f77749f9f9a5f0d7c99427e0311912a3fa04e7 10.103.16.34:7003 slave 89147e5837e378b69233dd2b8290267975719bc4 0 1493879665448 5 connected
d015a22abc57c021f568973f4f1c03c7a5c7b772 10.103.16.35:7001 master - 0 1493879663946 4 connected 0-5460
89147e5837e378b69233dd2b8290267975719bc4 10.103.16.35:7002 master - 0 1493879664948 5 connected 10923-16383
ce9d635236567ccde4c864f78863fa0a4b26f25a 10.103.16.35:7003 slave 363ecec54c92c2548dcab016146bdb4c104e5e84 0 1493879665949 6 connected
93a0e8d405959480fcbd310a5d15a92346c69d43 10.103.16.34:7002 slave d015a22abc57c021f568973f4f1c03c7a5c7b772 0 1493879664446 4 connected
363ecec54c92c2548dcab016146bdb4c104e5e84 10.103.16.34:7001 myself,master - 0 0 1 connected 5461-10922

能夠看到如今的集羣有六個節點,三個主節點和三個從節點。並且每一個主節點都會記錄本身分配的哈希槽,從中咱們能夠看到

103.16.35:7001 master - 0 1493879663946 4 connected 0-5460
10.103.16.34:7001 myself,master - 0 0 1 connected 5461-10922
10.103.16.35:7002 master - 0 1493879664948 5 connected 10923-16383

固然咱們也能夠對這些節點的哈希槽進行從新的分配,咱們如今打算將103.16.35:7001的前100個哈希槽移動到10.103.16.34:7001

[root@localhost redis7003]# redis-trib.rb reshard 10.103.16.34:7001

而後會提示我輸入數值以及從哪裏遷移到哪裏:

How many slots do you want to move (from 1 to 16384)? 100
What is the receiving node ID? 363ecec54c92c2548dcab016146bdb4c104e5e84
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:d015a22abc57c021f568973f4f1c03c7a5c7b772
Source node #2:done

執行完之後就能夠進行遷移了,遷移完之後咱們再打印出來節點信息看一下:

[root@localhost redis7003]# redis-cli -p 7001 cluster nodes
78f77749f9f9a5f0d7c99427e0311912a3fa04e7 10.103.16.34:7003 slave 89147e5837e378b69233dd2b8290267975719bc4 0 1493881167965 5 connected
d015a22abc57c021f568973f4f1c03c7a5c7b772 10.103.16.35:7001 master - 0 1493881166460 4 connected 101-5460
89147e5837e378b69233dd2b8290267975719bc4 10.103.16.35:7002 master - 0 1493881166962 5 connected 10923-16383
ce9d635236567ccde4c864f78863fa0a4b26f25a 10.103.16.35:7003 slave 363ecec54c92c2548dcab016146bdb4c104e5e84 0 1493881167465 7 connected
93a0e8d405959480fcbd310a5d15a92346c69d43 10.103.16.34:7002 slave d015a22abc57c021f568973f4f1c03c7a5c7b772 0 1493881167965 4 connected
363ecec54c92c2548dcab016146bdb4c104e5e84 10.103.16.34:7001 myself,master - 0 0 7 connected 0-100 5461-10922

咱們能夠很清楚的看到已經遷移成功了。

 
6:咱們來測試一下集羣的故障轉移功能
首先咱們要看一下集羣的主節點信息:
[root@localhost redis7003]# redis-cli -p 7001 cluster nodes | grep master
d015a22abc57c021f568973f4f1c03c7a5c7b772 10.103.16.35:7001 master - 0 1493883826713 4 connected 101-5460
89147e5837e378b69233dd2b8290267975719bc4 10.103.16.35:7002 master - 0 1493883827213 5 connected 10923-16383
363ecec54c92c2548dcab016146bdb4c104e5e84 10.103.16.34:7001 myself,master - 0 0 7 connected 0-100 5461-10922

咱們如今要使10.103.16.35:7001這個主節點斷掉,而後重啓看一下基本信息

[root@mxqmongodb2 sa]# /home/maxiangqian/redis-3.2.8/src/redis-cli -p 7001
127.0.0.1:7001> SHUTDOWN
not connected> exit
[root@mxqmongodb2 sa]# redis-server /home/redis7001/redis7001.conf

而後再打印一下集羣信息看一下:

[root@localhost redis7003]# redis-cli -p 7001 cluster nodes
78f77749f9f9a5f0d7c99427e0311912a3fa04e7 10.103.16.34:7003 slave 89147e5837e378b69233dd2b8290267975719bc4 0 1493884247801 5 connected
d015a22abc57c021f568973f4f1c03c7a5c7b772 10.103.16.35:7001 slave 93a0e8d405959480fcbd310a5d15a92346c69d43 0 1493884247300 8 connected
89147e5837e378b69233dd2b8290267975719bc4 10.103.16.35:7002 master - 0 1493884246798 5 connected 10923-16383
ce9d635236567ccde4c864f78863fa0a4b26f25a 10.103.16.35:7003 slave 363ecec54c92c2548dcab016146bdb4c104e5e84 0 1493884246298 7 connected
93a0e8d405959480fcbd310a5d15a92346c69d43 10.103.16.34:7002 master - 0 1493884248301 8 connected 101-5460
363ecec54c92c2548dcab016146bdb4c104e5e84 10.103.16.34:7001 myself,master - 0 0 7 connected 0-100 5461-10922

經過信息咱們能夠很明顯的看到了10.103.16.35:7001這個主節點已經變成了從節點,而自己他的從節點也上升爲主節點了。

可是咱們須要注意的是在故障轉移的時間段內,一些10.103.16.35:7001的寫操做是會丟失的。直到他的從庫提高爲主庫爲止,這是redis爲了保證數據一致性而採起的措施。
 
7:集羣的節點管理:
咱們先看一下怎麼添加節點,添加節點分爲兩類(主節點或者從節點)
主節點:
./redis-trib.rb add-node 10.103.16.34:7004 10.103.16.34:7001

這樣咱們就把10.103.16.34:7004添加爲集羣的新的主節點,不過咱們要注意的是,這時候他僅僅是一個沒有哈希槽的主節點,並不會存儲任何數據。

咱們可使用 redis-trib 程序, 將集羣中的某些哈希桶移動到新節點裏面, 新節點就會成爲真正的主節點了。
從節點:
./redis-trib.rb add-node 10.103.16.34:7004 10.103.16.34:7001
redis 10.103.16.34::7004> cluster replicate 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e

將新節點指定爲ID爲3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e的從節點。

接下來咱們看一下怎麼移除某個節點,語法格式以下:
./redis-trib del-node 127.0.0.1:7000 `<node-id>`

可是咱們要注意一點,移除主節點的時候必須保證主節點是空的,也就是事先將要移除的主節點的哈希槽給轉移到其餘的主節點上。

相關文章
相關標籤/搜索