聲明:
本文只允許用于個人學習交流使用,如有錯誤之處請多多指正。
文檔版本:Version 1.0
修改記錄:2015-10-30
系統環境:RedHat Enterprise Linux Server release 6.2 (Santiago)
內核版本:Linuxzxt-02.com 2.6.32-220.el6.x86_64 #1 SMP Wed Nov 9 08:03:13 EST 2011 x86_64x86_64 x86_64 GNU/Linux
軟件版本:redis-3.0.5
主機名:redis-01.com、redis-02.com
主機IP:192.168.1.193 192.168.1.176
安裝所需軟件環境:
Zlib、ruby(必須1.9.2以上)、rubygem、gem-redis
注:在閱讀文本文檔之前需要讀者知道的是本文檔以及目前網絡上的大部分相近的文檔都來源于http://redis.io。如果您的英文閱讀能較好的話建議您閱讀Reis官方文檔。http://redis.io/topics/cluster-spec
http://redis.io/topics/cluster-tutorial
Redis 集群是一個可以在多個Redis節點之間進行數據共享的設施(installation)。Redis 集群不支持那些需要同時處理多個鍵的Redis 命令,因為執行這些命令需要在多個Redis 節點之間移動數據,并且在高負載的情況下,這些命令將降低Redis 集群的性能,并導致不可預測的行為。
Redis 集群通過分區(partition)來提供一定程度的可用性(availability):即使集群中有一部分節點失效或者無法進行通訊,集群也可以繼續處理命令請求。
Redis集群提供了以下兩個好處:
將數據自動切分(split)到多個節點的能力。
當集群中的一部分節點失效或者無法進行通訊時,仍然可以繼續處理命令請求的能力
Redis 集群沒有使用一致性hash,而是引入了哈希槽的概念.
Redis 集群有16384個哈希槽,每個key通過CRC16校驗后對16384取模來決定放置哪個槽.集群的每個節點負責一部分hash槽,舉個例子,比如當前集群有3個節點,那么:
節點 A 包含 0 到 5500號哈希槽
節點 B 包含5501 到 11000 號哈希槽.
節點 C 包含11001 到 16384號哈希槽.
這種結構很容易添加或者刪除節點. 比如如果我想新添加個節點D,我需要從節點 A, B, C中得部分槽到D上. 如果我像移除節點A,需要將A中得槽移到B和C節點上,然后將沒有任何槽的A節點從集群中移除即可.
由于從一個節點將哈希槽移動到另一個節點并不會停止服務,所以無論添加刪除或者改變某個節點的哈希槽的數量都不會造成集群不可用的狀態.
為了使在部分節點失敗或者大部分節點無法通信的情況下集群仍然可用,所以集群使用了主從復制模型,每個節點都會有N-1個復制品.
在我們例子中具有A,B,C三個節點的集群,在沒有復制模型的情況下,如果節點B失敗了,那么整個集群就會以為缺少5501-11000這個范圍的槽而不可用.
然而如果在集群創建的時候(或者過一段時間)我們為每個節點添加一個從節點A1,B1,C1,那么整個集群便有三個master節點和三個slave節點組成,這樣在節點B失敗后,集群便會選舉B1為新的主節點繼續服務,整個集群便不會因為槽找不到而不可用了
不過當B和B1 都失敗后,集群是不可用的.
Redis 并不能保證數據的強一致性.這意味這在實際中集群在特定的條件下可能會丟失寫操作.
第一個原因是因為集群是用了異步復制. 寫操作過程:
客戶端向主節點B寫入一條命令.
主節點B向客戶端回復命令狀態.
主節點將寫操作復制給他得從節點 B1,B2 和 B3.
主節點對命令的復制工作發生在返回命令回復之后, 因為如果每次處理命令請求都需要等待復制操作完成的話, 那么主節點處理命令請求的速度將極大地降低 —— 我們必須在性能和一致性之間做出權衡。
注意:Redis 集群可能會在將來提供同步寫的方法。
Redis 集群另外一種可能會丟失命令的情況是集群出現了網絡分區, 并且一個客戶端與至少包括一個主節點在內的少數實例被孤立。.
舉個例子 假設集群包含 A 、 B 、 C 、 A1 、 B1 、 C1 六個節點, 其中 A 、B 、C 為主節點, A1 、B1 、C1 為A,B,C的從節點, 還有一個客戶端 Z1
假設集群中發生網絡分區,那么集群可能會分為兩方,大部分的一方包含節點 A 、C 、A1 、B1 和 C1 ,小部分的一方則包含節點 B 和客戶端 Z1 .
Z1仍然能夠向主節點B中寫入, 如果網絡分區發生時間較短,那么集群將會繼續正常運作,如果分區的時間足夠讓大部分的一方將B1選舉為新的master,那么Z1寫入B中得數據便丟失了.
注意, 在網絡分裂出現期間, 客戶端 Z1 可以向主節點 B 發送寫命令的最大時間是有限制的, 這一時間限制稱為節點超時時間(node timeout),是 Redis 集群的一個重要的配置選項:
redis-cluster要求最少需要3個節點,由于測試環境我這里使用兩臺虛擬機安裝多個節點來模擬redis集群。
主機節點分配:
node1 192.168.1.193:6379
node2 192.168.1.193:6479
node3 192.168.1.193:6579
備機節點:
node1 192.168.1.176:6379
node2 192.168.1.176:6479
node3 192.168.1.176:6579
Zlib軟件可以根據心情選擇yum安裝或者編譯安裝
Yum安裝
[zxt@redis-01 ~]$ yum install -y zlib* [zxt@redis-01 ~]$ rpm -qa |grep zlib zlib-1.2.3-27.el6.x86_64 zlib-devel-1.2.3-27.el6.x86_64
編譯安裝:
#download: http://www.zlib.net/ tar zxf zlib-1.2.7.tar.gz cd zlib ./configure make make install
想要運行Redis cluter必須安裝ruby并需安裝1.9.2及以上版本。此處不要使用yum安裝,因為RedHat6.2系統yum安裝默認版本為1.8.7
#ruby-2.1.7.tar.gz tar zxvf ruby-2.1.7.tar.gz cd ruby-2.1.7 ./configure -prefix=/usr/local/ruby make make install cp ruby /usr/local/bin
# rubygems-1.8.5.tgz tar zxvf rubygems-1.8.5.tgz cd rubygems-1.8.5 ruby setup.rb cp bin/gem /usr/local/bin
安裝運行redis集群所必需的redis和ruby的接口。
gem install redis --version 3.0.5
#由于某些原因,gem源不能訪問或者可能下載失敗可能下載失敗,以下提供兩種解決方案:
法一:手動下載下來安裝
#download地址: http://rubygems.org/gems/redis/versions/3.0.0 gem install -l /soft/redis-3.0.5.gem
法二:更換gem 源
gem sources --removehttps://rubygems.org/ gem sources -ahttp://ruby.sdutlinux.org/ gem sources -l *** CURRENT SOURCES*** https://ruby.taobao.org
常用的源
http://rubygems.org/ http://gems.github.com http://gems.rubyforge.org http://ruby.sdutlinux.org/ #國內應該找個比較靠譜了,適合安裝大多數常見的gem
tar xzfredis-3.0.5.tar.gz cp -r redis-3.0.5 /opt/app/ ln -s /opt/app/redis-3.0.5/ /opt/redis cd /opt/redis make test make make install
說明:
make install命令執行完成后,會在/usr/local/bin目錄下生成本個可執行文件,分別是redis-server、redis-cli、redis-benchmark、redis-check-aof 、redis-check-dump,它們的作用如下:
redis-server:Redis服務器的daemon啟動程序
redis-cli:Redis命令行操作工具。也可以用telnet根據其純文本協議來操作
redis-benchmark:Redis性能測試工具,測試Redis在當前系統下的讀寫性能
redis-check-aof:數據修復
redis-check-dump:檢查導出工具
1)配置集群初始化腳本:
cd /opt/redis cp/opt/redis/src/redis-trib.rb /usr/local/bin
2)配置redis cluster配置文件
daemonize yes #以后臺進程redis運行. pidfile/opt/redis/run/redis_6379.pid #若以后臺進程運行Reids,則需指定pid文件及路徑. port 6379 #指定redis監聽端口. tcp-backlog 511 #在高并發的環境中,為避免客戶端的連接緩慢問題. bind 0.0.0.0 #綁定主機IP.(這里設置為4個0可以方便程序調用). timeout 0 #客戶端連接時的超時時間,單位為秒. tcp-keepalive 60 #在 Linux 上,指定值(秒)用于發送 ACKs 的時間,注意關閉連接需要雙倍的時間.默認為 0 loglevel notice #日志記錄等級,有4個可選值,debug,verbose(默認值),notice,warning logfile"/var/log/redis/redis_6379.log" #log 文件地址 databases 16 #可用數據庫數 save 900 1 save 300 10 save 60 10000 #根據給定的時間間隔和寫入次數將數據保存到磁盤,單位為秒 stop-writes-on-bgsave-erroryes #后臺存儲錯誤停止寫。 rdbcompression yes #存儲至本地數據庫時(持久化到dump.rdb文件)是否壓縮數據,默認為 yes rdbchecksum yes #是否校驗rdb文件. dbfilenamedump_6379.rdb #本地持久化數據庫文件名,默認值為 dump.rdb dir /opt/redis/data #數據庫鏡像備份的文件放置的路徑。 #slaveof<masterip> <masterport> #設置該數據庫為其他數據庫的從數據庫時啟用該參數。 #masterauth<master-password> #slave服務連接master的密碼 slave-serve-stale-datayes slave-read-only yes #slave只讀 repl-diskless-syncno repl-diskless-sync-delay5 repl-disable-tcp-nodelayno slave-priority 100 #requirepassfoobared #設置客戶端連接密碼 appendonly yes #打開aof持久化 appendfilename"appendonly_6379.aof" #aof文件名,默認為appendonly.aof appendfsync everysec #每秒一次aof寫 no-appendfsync-on-rewriteyes #關閉在aof rewrite的時候對新的寫操作進行fsync auto-aof-rewrite-percentage100 #部署在同一機器的redis實例,把auto-aof-rewrite搓開,因為cluster環境下內存占用基本一致. #防止同一機器下瞬間fork所有redis進程做aof rewrite,占用大量內存(ps:cluster必須開啟aof) auto-aof-rewrite-min-size64mb aof-load-truncatedyes lua-time-limit 5000 cluster-enabled yes #打開redis集群 cluster-config-filenodes-6379.conf #集群節點配置文件(啟動自動生成) cluster-node-timeout15000 #節點互連超時的閥值 cluster-migration-barrier1 slowlog-log-slower-than10000 slowlog-max-len 128 latency-monitor-threshold0 notify-keyspace-events"" hash-max-ziplist-entries512 hash-max-ziplist-value64 list-max-ziplist-entries512 list-max-ziplist-value64 set-max-intset-entries512 zset-max-ziplist-entries128 zset-max-ziplist-value64 hll-sparse-max-bytes3000 activerehashing yes client-output-buffer-limitnormal 0 0 0 client-output-buffer-limitslave 256mb 64mb 60 client-output-buffer-limitpubsub 32mb 8mb 60 hz 10 aof-rewrite-incremental-fsyncyes
注意:其他節點只需要復制配置文件將所有端口號更改即可。
192.1.168.1.193 cd /opt/redis redis-serverredis_6379.conf redis-serverredis_6479.conf redis-serverredis_6579.conf 192.1.168.1.193 cd /opt/redis redis-serverredis_6379.conf redis-serverredis_6479.conf redis-serverredis_6579.conf
啟動之后使用netstat –lntp 命令查看端口是否監聽,如圖所示則啟動正常。
redis-trib.rb create--replicas 1 192.168.1.193:6379 192.168.1.193:6479 192.168.1.193:6579 192.168.1.176:6379192.168.1.193:6479 192.168.1.193:6579
注:
#redis-trib.rb的create子命令構建
#--replicas則指定了為Redis Cluster中的每個Master節點配備幾個Slave節點
#節點角色由順序決定,先master之后是slave(為方便辨認,slave的端口比master大1000)
#redis-trib.rb的check子命令
#ip:port可以是集群的任意節點
redis-trib.rb check 192.168.1.193:6379
最后輸出如下信息,沒有任何警告或錯誤(如圖),表示集群啟動成功并處于ok狀態
創建一個空節點(empty node),然后將某些哈希插槽移動到這個空節點上。
a)、創建新節點配置文件:
為了方便區分我這里再開啟一臺虛擬機增加一對節點:
192.168.1.187:6379
192.168.1.187:6479
cd /opt/redis scp redis_6379.conf 192.168.1.187:/opt/redis/ cp redis_6379.conf redis_6479.conf sed –ie s/6379/6479/g redis_6479.conf
b)、啟動新節點:
redis-server redis_6379.conf
c)、將新節點加入集群:
redis-trib.rbadd-node 192.168.1.187:6379 192.168.1.193:6379
add-node 將一個節點添加到集群里面,第一個是新節點ip:port, 第二個是任意一個已存在節點ip:port
注意:在添加新節點時,新節點中不能包含任何數據,否則會添加失敗。
因為它沒有包含任何哈希插槽。新加入的加點是一個主節點,當集群需要將某個從節點升級為新的主節點時,這個新節點不會被選中,同時新的主節點因為沒有包含任何哈希插槽,不參加選舉和failover。
d)、手動為新節點添加哈希插槽:
redis-trib.rb reshard 192.168.1.187:6379
#根據提示選擇要遷移的哈希插槽數量
How many slots do you want to move (from 1 to 16384)? 1000
#選擇要接受這些哈希插槽的node-id
What is the receiving node ID? 36c46361327dbb15d098a0c3794ac3d72869e508
#選擇哈希插槽來源:
#all表示從所有的master重新分配,
#或者數據要提取哈希插槽的master節點id,最后用done結束
Please enter all the source node IDs.
Type 'all' to use all the nodes as sourcenodes for the hash slots.
Type 'done' once you entered all thesource nodes IDs.
Source node #1:all
#打印被移動的哈希插槽后,輸入yes開始移動哈希插槽以及對應的數據.
#Do you want to proceed with the proposed reshard plan (yes/no)?yes
#結束
可以使用命令查看對比哈希槽的分配情況(如圖)
redis-trib.rbcheck 192.168.1.176:6379
至此,一個新的主節點就添加完成了,執行命令查看現在的集群中節點的狀態
redis-trib.rbcheck 192.168.1.176:6379 redis-cli-c -p 6379 cluster nodes
a):前三步操作同添加master一樣
注意:新添加的節點群集默認分配為master但是節點沒有分配任何插槽(如圖)
b)第四步:redis-cli連接上新節點shell,輸入命令:clusterreplicate 對應master的node-id(這里我們輸入節點192.168.1.187:6379的id)。
redis-cli -h 192.168.1.187 -p 6479 clusterreplicate 36c46361327dbb15d098a0c3794ac3d72869e508 exit
也可通過查看集群狀態確定是否添加成功
注意:在線添加slave 時,需要bgsave整個master數據,并傳遞到slave,再由 slave加載rdb文件到內存,rdb生成和傳輸的過程中消耗Master大量內存和網絡IO,以此不建議單實例內存過大,線上小心操作。
法一:
#redis-tribdel-node ip:port '<node-id>' redis-trib.rbdel-node 192.168.1.187:6479 4655fccff00ef4a7b99c10ffd590c8328ec6db8d
法二:直接停止或kill掉 節點即可
Redis-cli–p 6479 shutdown or kill-9 `cat /opt/redis/run/redis_6479.pid`
a):刪除master節點之前首先要使用reshard移除master的全部slot,然后再刪除當前節點
#把192.168.1.187:6379當前master遷移到192.168.1.176:6579上
redis-trib.rbreshard 192.168.1.176:6579
#根據提示選擇要遷移的哈希插槽數量
How manyslots do you want to move (from 1 to 16384)? 1000
(被刪除master的所有哈希插槽數量)
#選擇要接受這些哈希插槽的192.168.1.176:6579
What isthe receiving node ID? e1c06dd4682a37eb6773d6cb1d5709034a3f2769(ps: 192.168.1.176:6579的node-id)
Pleaseenter 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.
Sourcenode #36c46361327dbb15d098a0c3794ac3d72869e508 (被刪除master的node-id)
Sourcenode #2:done
#打印被移動的哈希插槽后,輸入yes開始移動哈希插槽以及對應的數據.
#Do youwant to proceed with the proposed reshard plan (yes/no)? yes
b):刪除空master節點
redis-trib.rbdel-node 192.168.1.187:6379 '36c46361327dbb15d098a0c3794ac3d72869e508'
1、查看集群狀態
redis-trib.rbcheck 127.0.0.1:6379
2、查看集群信息
redis-cli-c –p 6379 cluster nodes
3、查看集群主從情況
redis-cli-c -p 6379 info Replication
4、查看集群信息
redis-cli-c –p 6379 cluster info
集群
CLUSTER INFO 打印集群的信息
CLUSTER NODES 列出集群當前已知的所有節點(node),以及這些節點的相關信息。
節點
CLUSTER MEET <ip> <port> 將 ip 和 port 所指定的節點添加到集群當中,讓它成為集群的一份子。
CLUSTER FORGET <node_id> 從集群中移除node_id 指定的節點。
CLUSTER REPLICATE <node_id> 將當前節點設置為node_id 指定的節點的從節點。
CLUSTER SAVECONFIG 將節點的配置文件保存到硬盤里面。
槽(slot)
CLUSTER ADDSLOTS <slot> [slot ...] 將一個或多個槽(slot)指派(assign)給當前節點。
CLUSTER DELSLOTS <slot> [slot ...] 移除一個或多個槽對當前節點的指派。
CLUSTER FLUSHSLOTS 移除指派給當前節點的所有槽,讓當前節點變成一個沒有指派任何槽的節點。
CLUSTER SETSLOT <slot> NODE<node_id> 將槽 slot 指派給 node_id 指定的節點,如果槽已經指派給另一個節點,那么先讓另一個節點刪除該槽>,然后再進行指派。
CLUSTER SETSLOT <slot> MIGRATING<node_id> 將本節點的槽 slot 遷移到 node_id 指定的節點中。
CLUSTER SETSLOT <slot> IMPORTING<node_id> 從 node_id 指定的節點中導入槽 slot 到本節點。
CLUSTER SETSLOT <slot> STABLE 取消對槽 slot 的導入(import)或者遷移(migrate)。
鍵
CLUSTER KEYSLOT <key> 計算鍵 key 應該被放置在哪個槽上。
CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的鍵值對數量。
CLUSTER GETKEYSINSLOT <slot><count> 返回 count 個slot 槽中的鍵。
http://hot66hot.iteye.com/blog/2050676/
Redis指令大全:
http://redis.io/commands
一個redis愛好者創建的相關問題討論網站:
http://www.rediscookbook.org/
為什么使用 Redis及其產品定位:
http://www.infoq.com/cn/articles/tq-why-choose-redis
Redis內存使用優化與存儲:
http://www.infoq.com/cn/articles/tq-redis-memory-usage-optimization-storage
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。