背景
在測試服務(wù)器(CentOS 系統(tǒng))上搭建 Redis 集群,這里一步步實踐并整理一些較好的步驟芋忿。
正文
簡單安裝請參照官方文檔:Redis Quick Start炸客。
- 前提
- 搭建
- 測試
- 維護
前提
在搭建集群之前,需要明確一下情況戈钢。
版本
目前安裝的是3.2.11
版本痹仙,在有些 CentOS 上內(nèi)置的就是它,所以導(dǎo)致目前項目都用的這個版本逆趣。安裝
默認的編譯安裝只需要使用make install
命令蝶溶,所以依賴的無非是gcc
和gcc-c++
這兩個編譯工具嗜历,install
命令也僅僅是將redis-*
系列拷貝到/usr/local/bin
目錄下宣渗。更正確的配置
建立/etc/redis
和/var/redis
目錄,拷貝redis.conf
為/etc/redis/6380.conf
梨州。
在6380.conf
中痕囱,bind
設(shè)為192.168.1.57
,port
設(shè)為6380
暴匠,daemonize
設(shè)為yes
鞍恢,pidfile
指向/var/run/redis_6380.pid
,logfile
指向/var/log/redis_6380.log
每窖,dir
指向/var/redis/6380
帮掉。
搭建
有了前提條件,接下來就參考官方 Redis Cluster 文檔來實踐一番窒典。
- 配置
- 創(chuàng)建
配置
集群的配置稍微比【更正確的配置】要多一些蟆炊。
根據(jù) Redis Cluster 以及 redis.conf
中的解釋:
cluster-enable yes
yes
表示在特定實例(以此配置文件啟動的實例)中啟用集群支持;no
表示作為獨立實例啟動瀑志。cluster-config-file nodes.conf
每個集群節(jié)點都有這個配置文件涩搓,但用戶不能手動編輯內(nèi)容,它是由節(jié)點自己創(chuàng)建和更新劈猪。每個節(jié)點需要有不同的配置文件昧甘,請確保同一個系統(tǒng)中的不同節(jié)點,不會覆蓋這個配置文件(即:不同的實例战得,配置文件中的dir
必須指向不同的目錄)充边。cluster-node-timeout 5000
集群節(jié)點超時是節(jié)點在確認失敗的狀態(tài)下,持續(xù)不可訪問的毫秒總時長常侦,大多數(shù)其他內(nèi)部時間限制是節(jié)點超時的倍數(shù)浇冰。cluster-slave-validity-factor 0
對于主節(jié)點來說予弧,這個因數(shù)乘以超時值,表示主節(jié)點最終確認故障的時間范圍湖饱;對于從節(jié)點來說掖蛤,在因數(shù)乘以超時值的時間范圍內(nèi),將不會進行故障轉(zhuǎn)移(成為主節(jié)點)井厌。如果因數(shù)設(shè)為 0蚓庭,則始終在主節(jié)點不可用時進行故障切換,這也是唯一能保證最大可用性的參數(shù)仅仆。cluster-migration-barrier 1
默認是1器赞,表示所有主節(jié)點在正常狀態(tài)下,應(yīng)當保持的從節(jié)點數(shù)量墓拜。比如當前主節(jié)點擁有 2 個從節(jié)點港柜,另外有個主節(jié)點的從節(jié)點出現(xiàn)故障,又沒有其他從節(jié)點可用咳榜,此時當前主節(jié)點下的一個從節(jié)點會自動遷移到另外的主節(jié)點下夏醉。如果當前主節(jié)點只有 1 個從節(jié)點,那么將不會進行切換涌韩。這個值可以是 0畔柔,在調(diào)試時可用,但在生產(chǎn)中很危險臣樱。cluster-require-full-coverage yes
yes
是默認情況靶擦,表示只要有一個散列槽未被使用(沒有節(jié)點服務(wù)于它),那么集群將不可用雇毫;no
表示服務(wù)于其他散列槽的節(jié)點繼續(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)建需要先啟動實例席吴,可以拷貝啟動腳本 /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
命令啟動實例孝冒。
實例啟動狀態(tài)如下:
為了保證集群最小可用性柬姚,需要在 192.168.1.127
和 192.168.1.8
上面也啟動 6380
和 6381
實例品山。
另外需要安裝:
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ù)表示希望每個主節(jié)點都有指定的從節(jié)點往衷,這里是 1 個骑篙。后面的 IP 地址 + 端口號削彬,就是初始創(chuàng)建的集群列表。
創(chuàng)建成功:
如果多臺服務(wù)器配置起來很繁瑣忧风,可以試著用一下:Redis Cluster 腳本默色。
測試
參考官方文檔進行測試。
嘗試連接:
redis-cli -c -p 6380
連接失斒ㄍ取:
這是集群 bind
了一個局域網(wǎng)地址腿宰,需要使用 -h
設(shè)置 IP 地址參數(shù):
redis-cli -c -h 192.168.1.8 -p 6380
成功連接:
測試通過:
維護
首先,需要有 2.2.2
以上的 Ruby
環(huán)境缘厢,然后去 redis-rb-cluster 下載文件:
- 簡單示例 + 重新分片
- 有趣示例 + 故障轉(zhuǎn)移
- 其他維護命令
簡單示例 + 重新分片
對于 example.rb
文件吃度,需要修改的地方是:
if ARGV.length != 2
startup_nodes = [
{:host => "192.168.1.8", :port => 6380},
{:host => "192.168.1.8", :port => 6381}
]
else
然后開始運行 ruby ./example.rb
,接著會得到一長串的數(shù)字遞增贴硫,此時可以保留這個窗口椿每。
打開新的窗口,準備重新分片:
redis-trib.rb reshard 192.168.1.8:6380
顯示結(jié)果:
移動 1000
個哈希槽(建議保持 example.rb
在運行狀態(tài)):
需要一個目標節(jié)點的 ID英遭,這從【顯示結(jié)果】的圖中可以找到:
輸入 0471fb34c39dbb9338b56c474f59b3e745a1cc8f
之后间护,會被詢問從哪些節(jié)點獲取哈希槽:
官方指引輸入 all
:
但我這邊 出現(xiàn)錯誤,那么使用 check
參數(shù)檢查哪里出了問題:
再按照提示贪绘,使用 fix
參數(shù)修復(fù)問題(我嘗試過從編譯文件更新 redis-trib.rb
文件):
問題依然存在兑牡,自動修復(fù)出錯央碟。
搜索 錯誤提示 后税灌,找到:redis cluster3.2.0注意點。
登陸客戶端:
redis-cli -c -h 192.168.1.8 -p 6380
執(zhí)行命令:
cluster setslot 5461 stable
效果如圖:
再檢查一下:
有可能還需要對 192.168.1.127:6380
進行同樣的操作:
OK亿虽!總算恢復(fù)了正常菱涤。
再試試在停止 example.rb
腳本的情況下,執(zhí)行重新分片:
這是從 192.168.1.8
的 主節(jié)點 6380
開始洛勉,執(zhí)行 1000
個哈希槽的重新分片粘秆,從所有節(jié)點轉(zhuǎn)移到 192.168.1.127
的 主節(jié)點 6380
中,依然是同樣的錯誤收毫。
說明應(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
摘符,再不行不搞了。
當然,得先啟動 example.rb
逛裤,得到最佳效果瘩绒,然后再重新分片:
完美!4濉锁荔!沒有出錯:
測試一下運行狀態(tài):
正如預(yù)期的那樣,從其他主節(jié)點分配總共 1000
個哈希槽到 192.168.1.127
主節(jié)點中蝙砌。
可以將 重新分片 的操作匯合成一條命令:
./redis-trib.rb reshard --from <node-id> --to <node-id> --slots <number of slots> --yes <host>:<port>
有趣示例 + 故障轉(zhuǎn)移
接下來我們運行 consistency-test.rb
來看看一致性問題:
ruby ./consistency-test.rb 192.168.1.8 6380
效果如圖:
手動重置計數(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é)點 192.168.1.127:6381
的從節(jié)點嘱丢,原來的從節(jié)點 192.168.1.8:6381
成為主節(jié)點 192.168.1.127:6380
的從節(jié)點(意味著并沒有升級為主節(jié)點)。
其他維護命令
-
手動故障轉(zhuǎn)移:
cluster failover
(需要用redis-cli
登錄從節(jié)點)
通常在沒有故障但需要切換主從節(jié)點時使用祠饺,具體細節(jié)參考:cluster-failover越驻。
效果如圖:
-
添加新節(jié)點:
redis-trib.rb add-node 192.168.1.8:6382 192.168.1.8:6380
第一個參數(shù)是新建立的 Redis 實例,它是一個空節(jié)點道偷;第二個參數(shù)是集群中任何一個已存在的節(jié)點缀旁。
效果如圖:
通過192.168.1.8:6382
客戶端,檢查集群:
提示:空節(jié)點已加入集群勺鸦,但它沒有分配哈希槽并巍,因此也沒有任何數(shù)據(jù),不會被其他從節(jié)點選擇作為主人换途。
可以重新分片懊渡,以便重新分配哈希槽,但基本上無用军拟,只是在重新分區(qū)剃执。 -
添加新節(jié)點為副本:
redis-trib.rb add-node --slave 192.168.1.8:6382 192.168.1.8:6380
但這是不可能有效的:
必須要是一個空節(jié)點,才能這樣做懈息,那已經(jīng)成為主節(jié)點的192.168.1.8:6382
怎么辦肾档?
可以使用cluster replicate [id]
來成為目標節(jié)點的從節(jié)點:
-
刪除節(jié)點:
redis-trib.rb del-node 192.168.1.8:6380 f049c4f7a81a34f5a66248306f82e6317404b84d
第一個參數(shù)是集群中任何一個節(jié)點;第二個參數(shù)是需要刪除的節(jié)點 ID辫继。
效果如圖:
如果要用這個命令刪除主節(jié)點怒见,那么此主節(jié)點 必須為空,否則就要把它的數(shù)據(jù)重新分配給所有其他主節(jié)點姑宽。另外一種辦法是使用cluster replicate [id]
將主節(jié)點降級遣耍,成為從節(jié)點之后,可以繼續(xù)刪除節(jié)點低千。如果你必須減少集群中的主節(jié)點數(shù)量配阵,那么你應(yīng)該重新分片馏颂,使某些主節(jié)點不再擁有哈希槽和數(shù)據(jù),然后再刪除它們棋傍。 -
副本遷移:
cluster replicate [id]
簡單來說救拉,當你不希望某個主節(jié)點下的從節(jié)點先掛掉,然后主節(jié)點相繼掛掉瘫拣,此時集群處于不可用狀態(tài)(沒有掛掉主節(jié)點的哈希槽副本)亿絮,那么你就應(yīng)該執(zhí)行這些步驟:- 每個主節(jié)點至少分配一個從節(jié)點
- 額外增加一些從節(jié)點,可以是集群中的任意主節(jié)點
- 所有集群節(jié)點的配置參數(shù)麸拄,
cluster-migration-barrier
設(shè)為1
派昧,保證遷移功能正常
升級節(jié)點:
cluster replicate [id]
同樣的命令,但可以做很多事情拢切。概念比較復(fù)雜蒂萎,建議閱讀官方文檔 Redis Cluster,在此不做誤人解釋淮椰。遷移群集
概念比較復(fù)雜五慈,建議同上。
總結(jié)
Redis 集群比其他 NoSQL
數(shù)據(jù)庫復(fù)雜得多主穗,據(jù)我所知泻拦,Cassnadra
和 Elasticsearch
只需要修改配置,啟動忽媒,然后便是正常使用争拐。即使前面以單機形式啟動過,也只需要刷新一下系統(tǒng)信息表而已晦雨。
復(fù)雜的事物總顯得高大上架曹,希望后面維護起來會比 Cassandra
和 Elasticsearch
要輕松很多吧。