【實(shí)踐】Redis 集群搭建

背景

在測試服務(wù)器(CentOS 系統(tǒng))上搭建 Redis 集群,這里一步步實(shí)踐并整理一些較好的步驟。

正文

簡單安裝請參照官方文檔:Redis Quick Start。

  • 前提
  • 搭建
  • 測試
  • 維護(hù)

前提

在搭建集群之前,需要明確一下情況。

  • 版本
    目前安裝的是 3.2.11 版本,在有些 CentOS 上內(nèi)置的就是它,所以導(dǎo)致目前項(xiàng)目都用的這個(gè)版本。

  • 安裝
    默認(rèn)的編譯安裝只需要使用 make install 命令,所以依賴的無非是 gccgcc-c++ 這兩個(gè)編譯工具,install 命令也僅僅是將 redis-* 系列拷貝到 /usr/local/bin 目錄下。

  • 更正確的配置
    建立 /etc/redis/var/redis 目錄,拷貝 redis.conf/etc/redis/6380.conf。
    6380.conf 中,bind 設(shè)為 192.168.1.57port 設(shè)為 6380,daemonize 設(shè)為 yes,pidfile 指向 /var/run/redis_6380.pid,logfile 指向 /var/log/redis_6380.logdir 指向 /var/redis/6380

搭建

有了前提條件,接下來就參考官方 Redis Cluster 文檔來實(shí)踐一番。

  • 配置
  • 創(chuàng)建

配置

集群的配置稍微比【更正確的配置】要多一些。

根據(jù) Redis Cluster 以及 redis.conf 中的解釋:

  • cluster-enable yes
    yes 表示在特定實(shí)例(以此配置文件啟動的實(shí)例)中啟用集群支持;no 表示作為獨(dú)立實(shí)例啟動。

  • cluster-config-file nodes.conf
    每個(gè)集群節(jié)點(diǎn)都有這個(gè)配置文件,但用戶不能手動編輯內(nèi)容,它是由節(jié)點(diǎn)自己創(chuàng)建和更新。每個(gè)節(jié)點(diǎn)需要有不同的配置文件,請確保同一個(gè)系統(tǒng)中的不同節(jié)點(diǎn),不會覆蓋這個(gè)配置文件(即:不同的實(shí)例,配置文件中的 dir 必須指向不同的目錄)。

  • cluster-node-timeout 5000
    集群節(jié)點(diǎn)超時(shí)是節(jié)點(diǎn)在確認(rèn)失敗的狀態(tài)下,持續(xù)不可訪問的毫秒總時(shí)長,大多數(shù)其他內(nèi)部時(shí)間限制是節(jié)點(diǎn)超時(shí)的倍數(shù)。

  • cluster-slave-validity-factor 0
    對于主節(jié)點(diǎn)來說,這個(gè)因數(shù)乘以超時(shí)值,表示主節(jié)點(diǎn)最終確認(rèn)故障的時(shí)間范圍;對于從節(jié)點(diǎn)來說,在因數(shù)乘以超時(shí)值的時(shí)間范圍內(nèi),將不會進(jìn)行故障轉(zhuǎn)移(成為主節(jié)點(diǎn))。如果因數(shù)設(shè)為 0,則始終在主節(jié)點(diǎn)不可用時(shí)進(jìn)行故障切換,這也是唯一能保證最大可用性的參數(shù)。

  • cluster-migration-barrier 1
    默認(rèn)是1,表示所有主節(jié)點(diǎn)在正常狀態(tài)下,應(yīng)當(dāng)保持的從節(jié)點(diǎn)數(shù)量。比如當(dāng)前主節(jié)點(diǎn)擁有 2 個(gè)從節(jié)點(diǎn),另外有個(gè)主節(jié)點(diǎn)的從節(jié)點(diǎn)出現(xiàn)故障,又沒有其他從節(jié)點(diǎn)可用,此時(shí)當(dāng)前主節(jié)點(diǎn)下的一個(gè)從節(jié)點(diǎn)會自動遷移到另外的主節(jié)點(diǎn)下。如果當(dāng)前主節(jié)點(diǎn)只有 1 個(gè)從節(jié)點(diǎn),那么將不會進(jìn)行切換。這個(gè)值可以是 0,在調(diào)試時(shí)可用,但在生產(chǎn)中很危險(xiǎn)。

  • cluster-require-full-coverage yes
    yes 是默認(rèn)情況,表示只要有一個(gè)散列槽未被使用(沒有節(jié)點(diǎn)服務(wù)于它),那么集群將不可用;no 表示服務(wù)于其他散列槽的節(jié)點(diǎn)繼續(xù)接受查詢。

完整的配置參數(shù)如下:

bind 192.168.1.57
protected-mode yes
port 6380
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize yes
supervised no
pidfile /var/run/redis_6380.pid
loglevel notice
logfile "/var/log/redis_6380.log"
database 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/redis/6380
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay on
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
aof-load-truncated yes
lua-time-limit 5000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-slave-validity-factor 0
cluster-migration-barrier 1
cluster-require-full-coverage yes
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
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

創(chuàng)建

為了建立主從模式,將 6380.conf 拷貝一份 6381.conf,然后 修改所有端口相關(guān)參數(shù),以及建立相應(yīng)的 /var/redis/6380/var/redis/6381 目錄。

集群的創(chuàng)建需要先啟動實(shí)例,可以拷貝啟動腳本 /usr/local/redis/redis-3.2.11/utils/redis_init_script
/etc/init.d/redis_6380/etc/init.d/redis_6381,修改所有相關(guān)端口參數(shù) 后,再使用 sudo /etc/init.d/redis_6380 start 命令啟動實(shí)例。

實(shí)例啟動狀態(tài)如下:

為了保證集群最小可用性,需要在 192.168.1.127192.168.1.8 上面也啟動 63806381 實(shí)例。

另外需要安裝:

sudo gem install redis

對于 Redis 3.2.11 版本來說,應(yīng)該安裝(否則,會遇到后面【重新分片】的坑):

sudo gem install redis -v 3.3.3

注意:gem 需要 ruby 2.2.2 以上版本,請知悉。

隨后使用命令創(chuàng)建集群:

redis-trib.rb create --replicas 1 192.168.1.8:6380 192.168.1.8:6381 192.168.1.127:6380 192.168.1.127:6381 192.168.1.57:6380 192.168.1.57:6381

注意:--replicas 參數(shù)表示希望每個(gè)主節(jié)點(diǎn)都有指定的從節(jié)點(diǎn),這里是 1 個(gè)。后面的 IP 地址 + 端口號,就是初始創(chuàng)建的集群列表。

創(chuàng)建成功:

如果多臺服務(wù)器配置起來很繁瑣,可以試著用一下:Redis Cluster 腳本。

測試

參考官方文檔進(jìn)行測試。

嘗試連接:

redis-cli -c -p 6380

連接失?。?/p>

這是集群 bind 了一個(gè)局域網(wǎng)地址,需要使用 -h 設(shè)置 IP 地址參數(shù):

redis-cli -c -h 192.168.1.8 -p 6380

成功連接:

測試通過:

維護(hù)

首先,需要有 2.2.2 以上的 Ruby 環(huán)境,然后去 redis-rb-cluster 下載文件:

  • 簡單示例 + 重新分片
  • 有趣示例 + 故障轉(zhuǎn)移
  • 其他維護(hù)命令

簡單示例 + 重新分片

對于 example.rb 文件,需要修改的地方是:

if ARGV.length != 2
        startup_nodes = [
                {:host => "192.168.1.8", :port => 6380},
                {:host => "192.168.1.8", :port => 6381}
        ]
else

然后開始運(yùn)行 ruby ./example.rb,接著會得到一長串的數(shù)字遞增,此時(shí)可以保留這個(gè)窗口。

打開新的窗口,準(zhǔn)備重新分片:

redis-trib.rb reshard 192.168.1.8:6380

顯示結(jié)果:

移動 1000 個(gè)哈希槽(建議保持 example.rb 在運(yùn)行狀態(tài)):

需要一個(gè)目標(biāo)節(jié)點(diǎn)的 ID,這從【顯示結(jié)果】的圖中可以找到:

輸入 0471fb34c39dbb9338b56c474f59b3e745a1cc8f 之后,會被詢問從哪些節(jié)點(diǎn)獲取哈希槽:

官方指引輸入 all

但我這邊 出現(xiàn)錯(cuò)誤,那么使用 check 參數(shù)檢查哪里出了問題:

再按照提示,使用 fix 參數(shù)修復(fù)問題(我嘗試過從編譯文件更新 redis-trib.rb 文件):

問題依然存在,自動修復(fù)出錯(cuò)。

搜索 錯(cuò)誤提示 后,找到:redis cluster3.2.0注意點(diǎn)。

登陸客戶端:

redis-cli -c -h 192.168.1.8 -p 6380

執(zhí)行命令:

cluster setslot 5461 stable

效果如圖:

再檢查一下:

有可能還需要對 192.168.1.127:6380 進(jìn)行同樣的操作:

OK!總算恢復(fù)了正常。

再試試在停止 example.rb 腳本的情況下,執(zhí)行重新分片:

這是從 192.168.1.8 的 主節(jié)點(diǎn) 6380 開始,執(zhí)行 1000 個(gè)哈希槽的重新分片,從所有節(jié)點(diǎn)轉(zhuǎn)移到 192.168.1.127 的 主節(jié)點(diǎn) 6380 中,依然是同樣的錯(cuò)誤。

說明應(yīng)該是 redis-trib.rb 腳本出了問題,但我嘗試過拷貝相同版本編譯后的文件,問題依然得不到解決。

百度不出來什么結(jié)果,于是谷歌一下,立即得到答案:

Just installing an earlier version of redis.rb fixes the issue. This worked for me:
gem install redis -v 3.3.3

原問題貼在這里:https://github.com/antirez/redis/issues/4272

執(zhí)行效果:

那么,我最后再嘗試一下 reshard,再不行不搞了。

當(dāng)然,得先啟動 example.rb,得到最佳效果,然后再重新分片:

完美?。。]有出錯(cuò):

測試一下運(yùn)行狀態(tài):

正如預(yù)期的那樣,從其他主節(jié)點(diǎn)分配總共 1000 個(gè)哈希槽到 192.168.1.127 主節(jié)點(diǎn)中。

可以將 重新分片 的操作匯合成一條命令:

./redis-trib.rb reshard --from <node-id> --to <node-id> --slots <number of slots> --yes <host>:<port>

有趣示例 + 故障轉(zhuǎn)移

接下來我們運(yùn)行 consistency-test.rb 來看看一致性問題:

ruby ./consistency-test.rb 192.168.1.8 6380

效果如圖:

手動重置計(jì)數(shù)器:

redis-cli -c -h 192.168.1.8 -p 6380 set key_217 0

并沒有出現(xiàn) 114 lost,但我已經(jīng)不想追究根源,還不如測試一下故障轉(zhuǎn)移:

redis-cli -c -h 192.168.1.8 -p 6380 debug segfault

看到了信息:

現(xiàn)在我們重新啟動 192.168.1.8:6380,然后查看集群狀態(tài):

可以發(fā)現(xiàn):192.168.1.8:6380 成為新主節(jié)點(diǎn) 192.168.1.127:6381 的從節(jié)點(diǎn),原來的從節(jié)點(diǎn) 192.168.1.8:6381 成為主節(jié)點(diǎn) 192.168.1.127:6380 的從節(jié)點(diǎn)(意味著并沒有升級為主節(jié)點(diǎn))。

其他維護(hù)命令

  • 手動故障轉(zhuǎn)移:cluster failover(需要用 redis-cli 登錄從節(jié)點(diǎn))
    通常在沒有故障但需要切換主從節(jié)點(diǎn)時(shí)使用,具體細(xì)節(jié)參考:cluster-failover。
    效果如圖:

  • 添加新節(jié)點(diǎn):redis-trib.rb add-node 192.168.1.8:6382 192.168.1.8:6380
    第一個(gè)參數(shù)是新建立的 Redis 實(shí)例,它是一個(gè)空節(jié)點(diǎn);第二個(gè)參數(shù)是集群中任何一個(gè)已存在的節(jié)點(diǎn)。
    效果如圖:


    通過 192.168.1.8:6382 客戶端,檢查集群:

    提示:空節(jié)點(diǎn)已加入集群,但它沒有分配哈希槽,因此也沒有任何數(shù)據(jù),不會被其他從節(jié)點(diǎn)選擇作為主人。
    可以重新分片,以便重新分配哈希槽,但基本上無用,只是在重新分區(qū)。

  • 添加新節(jié)點(diǎn)為副本:redis-trib.rb add-node --slave 192.168.1.8:6382 192.168.1.8:6380
    但這是不可能有效的:


    必須要是一個(gè)空節(jié)點(diǎn),才能這樣做,那已經(jīng)成為主節(jié)點(diǎn)的 192.168.1.8:6382 怎么辦?
    可以使用 cluster replicate [id] 來成為目標(biāo)節(jié)點(diǎn)的從節(jié)點(diǎn):

  • 刪除節(jié)點(diǎn):redis-trib.rb del-node 192.168.1.8:6380 f049c4f7a81a34f5a66248306f82e6317404b84d
    第一個(gè)參數(shù)是集群中任何一個(gè)節(jié)點(diǎn);第二個(gè)參數(shù)是需要?jiǎng)h除的節(jié)點(diǎn) ID。
    效果如圖:


    如果要用這個(gè)命令刪除主節(jié)點(diǎn),那么此主節(jié)點(diǎn) 必須為空,否則就要把它的數(shù)據(jù)重新分配給所有其他主節(jié)點(diǎn)。另外一種辦法是使用 cluster replicate [id] 將主節(jié)點(diǎn)降級,成為從節(jié)點(diǎn)之后,可以繼續(xù)刪除節(jié)點(diǎn)。如果你必須減少集群中的主節(jié)點(diǎn)數(shù)量,那么你應(yīng)該重新分片,使某些主節(jié)點(diǎn)不再擁有哈希槽和數(shù)據(jù),然后再刪除它們。

  • 副本遷移:cluster replicate [id]
    簡單來說,當(dāng)你不希望某個(gè)主節(jié)點(diǎn)下的從節(jié)點(diǎn)先掛掉,然后主節(jié)點(diǎn)相繼掛掉,此時(shí)集群處于不可用狀態(tài)(沒有掛掉主節(jié)點(diǎn)的哈希槽副本),那么你就應(yīng)該執(zhí)行這些步驟:

    1. 每個(gè)主節(jié)點(diǎn)至少分配一個(gè)從節(jié)點(diǎn)
    2. 額外增加一些從節(jié)點(diǎn),可以是集群中的任意主節(jié)點(diǎn)
    3. 所有集群節(jié)點(diǎn)的配置參數(shù),cluster-migration-barrier 設(shè)為 1,保證遷移功能正常
  • 升級節(jié)點(diǎn):cluster replicate [id]
    同樣的命令,但可以做很多事情。概念比較復(fù)雜,建議閱讀官方文檔 Redis Cluster,在此不做誤人解釋。

  • 遷移群集
    概念比較復(fù)雜,建議同上。

總結(jié)

Redis 集群比其他 NoSQL 數(shù)據(jù)庫復(fù)雜得多,據(jù)我所知,CassnadraElasticsearch 只需要修改配置,啟動,然后便是正常使用。即使前面以單機(jī)形式啟動過,也只需要刷新一下系統(tǒng)信息表而已。

復(fù)雜的事物總顯得高大上,希望后面維護(hù)起來會比 CassandraElasticsearch 要輕松很多吧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容