簡(jiǎn)介
redis以高效的讀寫性能,被非常多的企業(yè)用戶用來(lái)做數(shù)據(jù)緩存層,很多公司會(huì)根據(jù)自己業(yè)務(wù)場(chǎng)景,部署單點(diǎn)或者是redis的集群,但是單點(diǎn)的redis如果發(fā)生故障,是無(wú)法保證服務(wù)高可用的,所以現(xiàn)在緩存服務(wù)通常都是redis的集群。
redis的集群方案目前使用的比較多的幾種方式;
????基于codis的架構(gòu),部署的redis集群。
????基于redis的哨兵模式,部署一個(gè)master多slave的集群模式。
????redis從3.0開(kāi)始支持集群的部署方式,而且是無(wú)中心化的,多master多slave模式。?
本次主要介紹redis自己支持的cluster的方式部署以及簡(jiǎn)單應(yīng)用
集群架構(gòu)
首先是我們準(zhǔn)備的三臺(tái)服務(wù)器資源,規(guī)劃每臺(tái)服務(wù)器上部署一個(gè)master實(shí)例和一個(gè)slave實(shí)例。在每臺(tái)服務(wù)器上安裝好redis,規(guī)劃服務(wù)器列表如下:

介紹一下redis支持的cluster集群架構(gòu),redis cluster 集群節(jié)點(diǎn)類型分為master和slave,我們用組的概念理解一下,以master為類型進(jìn)行分組,一個(gè)組里面只有一個(gè)master,我們可以認(rèn)為是組長(zhǎng),其他的slave是組員,那數(shù)據(jù)存到redis集群里面,怎么存儲(chǔ)呢,redis集群默認(rèn)實(shí)現(xiàn)了一個(gè)hash slot的方式,哈希槽默認(rèn)是16384個(gè),也就是0-16383個(gè)槽,集群在創(chuàng)建的時(shí)候,每個(gè)組master會(huì)均勻分配這些槽,每個(gè)master占據(jù)一定的hash slot 范圍,往redis集群里面存儲(chǔ)數(shù)據(jù)的時(shí)候,redis默認(rèn)通過(guò)crc16(key)%16384 計(jì)算這個(gè)key的hash值,然后根據(jù)hash值找到對(duì)應(yīng)的master,直連該master進(jìn)行數(shù)據(jù)訪問(wèn)和存儲(chǔ)。redis集群里面所有實(shí)例都有hash slot對(duì)應(yīng)的master信息,所以連接任何一個(gè)實(shí)例信息,都能獲取到集群的ip和端口列表,然后根據(jù)計(jì)算出來(lái)的hash值,選擇具體的ip進(jìn)行直接訪問(wèn)。

安裝Redis
下載安裝redis:
## redis下載目錄可以參考:http://download.redis.io/releases/
wget http://download.redis.io/releases/redis-4.0.8.tar.gz
## 解壓文件
tar -xzf redis-4.0.8.tar.gz
## 進(jìn)入解壓目錄,編譯安裝
make
make install
centos服務(wù)器,也可以通過(guò)yum install redis 方式安裝,測(cè)試安裝結(jié)果。
redis-cli-v
在每臺(tái)服務(wù)器上啟動(dòng)redis-server,因?yàn)榉?wù)器資源有限,所以每臺(tái)服務(wù)器上部署兩個(gè)redis實(shí)例,當(dāng)然如果只有一臺(tái)服務(wù)器的情況下,也可以在一個(gè)服務(wù)器上部署多個(gè)實(shí)例,redis的配置文件如下,如果要部署多個(gè)實(shí)例注意修改端口號(hào)以及工作目錄和日志文件信息。
port 9002
bind? ? 0.0.0.0
daemonize? yes
logfile? "/root/temp/redis/redis-4.0.8/logs/node-9002.log"
cluster-enabled? yes
cluster-config-file? /root/temp/redis/redis-4.0.8/config/nodes-9002.conf
cluster-node-timeout? 5000
cluster-slave-validity-factor? ? 10
appendonly? yes
dir? /root/temp/redis/redis-4.0.8/data/9002
dbfilename? ? dump-9002.rdb
appendfilename? ? "appendonly-9002.aof"
redis-server啟動(dòng)以后可以查看每臺(tái)上的實(shí)例狀態(tài),下面開(kāi)始構(gòu)建集群。
如果是通過(guò)源碼安裝的redis,在src目錄下會(huì)有redis-trib.rb文件,這是ruby寫的一個(gè)腳本文件,redis的集群創(chuàng)建管理就是通過(guò)這個(gè)腳本來(lái)操作,所以在執(zhí)行這個(gè)腳本之前,首先還要保證服務(wù)器可以執(zhí)行ruby文件。執(zhí)行該腳本需要ruby版本>=2.2.2或者以上,檢查本機(jī)ruby的版本,如果版本過(guò)舊,可以通過(guò)以下操作升級(jí)ruby版本:
## 安裝rvm,Ruby version manager,Ruby的一個(gè)版本管理工具,如果使用過(guò)node,就跟nvm一樣,通過(guò)rvm可以看到ruby版本列表,可以很方便的進(jìn)行安裝和刪除。
## 安裝rvm的方式;
## gpg2是mac上的命令,linux服務(wù)器命令是gpg
gpg2 --keyserver hkp://keys.gnupg.net --recv-keys \ 409B6B1796C275462A1703113804BB82D39DC0E3 \ 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
curl -sSL https://get.rvm.io | bash -s stable
執(zhí)行命令安裝好以后,會(huì)有提示讓執(zhí)行source命令,讓rvm生效:
source $HOME/.rvm/scripts/rvm
## 查看安裝好的信息
rvm -v
## 查看ruby 版本列表
rvm list known
##安裝ruby版本2.5
rvm install 2.5
##安裝好ruby以后,還需要安裝redis的模塊。
gem install redis
## 如果在安裝redis模塊的時(shí)候很慢,可以更換ruby倉(cāng)庫(kù)源,使用aliyun的源倉(cāng)庫(kù)。
## gem source -a http://mirrors.aliyun.com/rubygems/
以上就安裝好ruby相關(guān)的環(huán)境了,然后我們就可以通過(guò)redis-trib.rb命令來(lái)管理集群了。
Redis集群創(chuàng)建
redis-trib.rb我是通過(guò)腳本的形式執(zhí)行的,也可以把他放到/usr/bin/目錄下,然后就可以執(zhí)行redis-trib命令了,可以查看redis-trib命令的先關(guān)幫助信息:
ruby redis-trib.rb help
Usage: redis-trib <command> <options> <arguments ...>
? create? ? ? ? ? host1:port1 ... hostN:portN
? ? ? ? ? ? ? ? ? --replicas <arg>
? check? ? ? ? ? host:port
? info? ? ? ? ? ? host:port
? fix? ? ? ? ? ? host:port
? ? ? ? ? ? ? ? ? --timeout <arg>
? reshard? ? ? ? host:port
? ? ? ? ? ? ? ? ? --from <arg>
? ? ? ? ? ? ? ? ? --to <arg>
? ? ? ? ? ? ? ? ? --slots <arg>
? ? ? ? ? ? ? ? ? --yes
? ? ? ? ? ? ? ? ? --timeout <arg>
? ? ? ? ? ? ? ? ? --pipeline <arg>
? rebalance? ? ? host:port
? ? ? ? ? ? ? ? ? --weight <arg>
? ? ? ? ? ? ? ? ? --auto-weights
? ? ? ? ? ? ? ? ? --use-empty-masters
? ? ? ? ? ? ? ? ? --timeout <arg>
? ? ? ? ? ? ? ? ? --simulate
? ? ? ? ? ? ? ? ? --pipeline <arg>
? ? ? ? ? ? ? ? ? --threshold <arg>
? add-node? ? ? ? new_host:new_port existing_host:existing_port
? ? ? ? ? ? ? ? ? --slave
? ? ? ? ? ? ? ? ? --master-id <arg>
? del-node? ? ? ? host:port node_id
? set-timeout? ? host:port milliseconds
? call? ? ? ? ? ? host:port command arg arg .. arg
? import? ? ? ? ? host:port
? ? ? ? ? ? ? ? ? --from <arg>
? ? ? ? ? ? ? ? ? --copy
? ? ? ? ? ? ? ? ? --replace
? help? ? ? ? ? ? (show this help)
For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.
上面的幫助詳細(xì)介紹了redis-trib的使用說(shuō)明,首先我們創(chuàng)建一個(gè)集群:
ruby redis-trib.rb create --replicas 1 192.168.35.66:7001 192.168.35.73:7001 192.168.35.74:7001 192.168.35.66:9002 192.168.35.73:9002 192.168.35.74:9002
介紹一下命令的參數(shù)信息:
create 是子命令,表示創(chuàng)建一個(gè)新的集群,并且創(chuàng)建集群的master節(jié)點(diǎn)必須>=3個(gè)才可以創(chuàng)建集群,replicas表示每個(gè)master有幾個(gè)slave,這里是1,表示每個(gè)master至少有一個(gè)slave實(shí)例。集群創(chuàng)建會(huì)彈出一個(gè)提示窗口,確認(rèn)沒(méi)有問(wèn)題的話,輸入yes,即可完成集群創(chuàng)建,然后通過(guò)check檢查集群狀態(tài):
ruby redis-trib.rb check 192.168.35.74:7001
>>> Performing Cluster Check (using node 192.168.35.74:7001)
M: c0be24752e6a23b566112c5389c20c35e97a5182 192.168.35.74:7001
? slots:5461-5797,10923-16383 (5798 slots) master
? 1 additional replica(s)
M: c1e9e762e553b5b62a674c439c8272447b2efc82 192.168.35.73:7001
? slots:5798-10922 (5125 slots) master
? 1 additional replica(s)
S: e00b99df51149512a4b4e6d64eec4d7550a63ede 192.168.35.73:9002
? slots: (0 slots) slave
? replicates 7a70746b2e23ee06e1bedb07f1952bfc9501a859
M: 7a70746b2e23ee06e1bedb07f1952bfc9501a859 192.168.35.66:7001
? slots:0-5460 (5461 slots) master
? 1 additional replica(s)
S: 82da7bd42cdd96785a2f131445c7b189c48c75a3 192.168.35.74:9002
? slots: (0 slots) slave
? replicates c0be24752e6a23b566112c5389c20c35e97a5182
S: 899a7a0199eeab0fcc5bce108efc2a57cf3d1d23 192.168.35.66:9002
? slots: (0 slots) slave
? replicates c1e9e762e553b5b62a674c439c8272447b2efc82
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
上面顯示我的集群狀態(tài)信息,slot分配的結(jié)果看上去可能不太均勻,這是因?yàn)槲易鲞^(guò)增減節(jié)點(diǎn),slot重新分配過(guò),如果想讓均衡一下,可以執(zhí)行如下命令:
##這個(gè)命令用來(lái)重新規(guī)劃集群各個(gè)勢(shì)力的負(fù)載
ruby redis-trib.rb rebalance? 192.168.35.74:7001
##重新規(guī)劃以后再通過(guò)check命令檢查,會(huì)發(fā)現(xiàn)redis的各個(gè)實(shí)例分配的slots很均勻了(命令輸出結(jié)果就不在這里貼出來(lái)了)
ruby redis-trib.rb check 192.168.35.74:7001
然后就會(huì)發(fā)現(xiàn)每個(gè)master分配的hash slot非常均衡了,有兩個(gè)是5461個(gè)slots,一個(gè)是5462個(gè)slots,執(zhí)行的命令就是rebalance。到此,我們的redis集群已經(jīng)創(chuàng)建完成了。
訪問(wèn)redis集群
現(xiàn)在通過(guò)redis-cli和應(yīng)用程序來(lái)訪問(wèn)一下集群信息。
## redis 訪問(wèn)集群的時(shí)候,需要執(zhí)行-c參數(shù)。
redis-cli -c -h 192.168.35.74 -p 7001
192.168.35.74:7001> get name
-> Redirected to slot [5798] located at 192.168.35.73:7001
"ggcc"
192.168.35.73:7001>
通過(guò)上面的執(zhí)行,發(fā)現(xiàn)獲取name值的時(shí)候一開(kāi)始我們連的是74這臺(tái)服務(wù)器,get命令執(zhí)行的時(shí)候,卻重定向到了73這臺(tái)服務(wù)器,所以client訪問(wèn)集群的時(shí)候,首先是根據(jù)key計(jì)算出來(lái)hash值,再根據(jù)hash值找到對(duì)應(yīng)的master實(shí)例節(jié)點(diǎn)信息,直連對(duì)應(yīng)的master實(shí)例,進(jìn)行數(shù)據(jù)的讀寫。
redis-cli命令是這樣執(zhí)行的,那么我們看Java程序是怎么讀寫數(shù)據(jù)的。
package redis;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class RedisClusterCli {
? ? public static void main(String[] args) {
? ? ? ? HostAndPort hostAndPort = new HostAndPort("192.168.35.74", 9002);
? ? ? ? Set<HostAndPort> hostAndPorts = new HashSet<>();
? ? ? ? hostAndPorts.add(hostAndPort);
? ? ? ? JedisCluster cluster = new JedisCluster(hostAndPorts);
? ? ? ? String value;
? ? ? ? while (true) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? System.out.println("請(qǐng)輸入key:");
? ? ? ? ? ? ? ? Scanner scanner = new Scanner(System.in);
? ? ? ? ? ? ? ? String key = scanner.next();
? ? ? ? ? ? ? ? value = cluster.get(key);
? ? ? ? ? ? ? ? System.out.println(value);
? ? ? ? ? ? } catch (Exception ex) {
? ? ? ? ? ? ? ? ex.printStackTrace();
? ? ? ? ? ? ? ? System.out.println("異常信息忽略");
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
測(cè)試代碼寫的比較簡(jiǎn)單,單獨(dú)執(zhí)行的話,能夠正常運(yùn)行,但是看不出具體的執(zhí)行細(xì)節(jié),我們查看一下關(guān)鍵部分的源碼,然后看一下它執(zhí)行的具體邏輯。redis.clients.jedis.JedisClusterCommand.runWithRetries方法
private T runWithRetries(byte[] key, int attempts, boolean tryRandomNode, boolean asking) {
? if (attempts <= 0) {
? ? throw new JedisClusterMaxRedirectionsException("Too many Cluster redirections?");
? }
? Jedis connection = null;
? try {
? ? if (asking) {
? ? ? // TODO: Pipeline asking with the original command to make it
? ? ? // faster....
? ? ? connection = askConnection.get();
? ? ? connection.asking();
? ? ? // if asking success, reset asking flag
? ? ? asking = false;
? ? } else {
? ? ? if (tryRandomNode) {
? ? ? ? connection = connectionHandler.getConnection();
? ? ? } else {
? ? ? ? connection = connectionHandler.getConnectionFromSlot(JedisClusterCRC16.getSlot(key));
? ? ? }
? ? }
? ? return execute(connection);
? } catch (JedisNoReachableClusterNodeException jnrcne) {
? ? throw jnrcne;
? } catch (JedisConnectionException jce) {
? ? // release current connection before recursion
? ? releaseConnection(connection);
? ? connection = null;
? ? if (attempts <= 1) {
? ? ? //We need this because if node is not reachable anymore - we need to finally initiate slots renewing,
? ? ? //or we can stuck with cluster state without one node in opposite case.
? ? ? //But now if maxAttempts = 1 or 2 we will do it too often. For each time-outed request.
? ? ? //TODO make tracking of successful/unsuccessful operations for node - do renewing only
? ? ? //if there were no successful responses from this node last few seconds
? ? ? this.connectionHandler.renewSlotCache();
? ? ? //no more redirections left, throw original exception, not JedisClusterMaxRedirectionsException, because it's not MOVED situation
? ? ? throw jce;
? ? }
? ? return runWithRetries(key, attempts - 1, tryRandomNode, asking);
? } catch (JedisRedirectionException jre) {
? ? // if MOVED redirection occurred,
? ? if (jre instanceof JedisMovedDataException) {
? ? ? // it rebuilds cluster's slot cache
? ? ? // recommended by Redis cluster specification
? ? ? this.connectionHandler.renewSlotCache(connection);
? ? }
? ? // release current connection before recursion or renewing
? ? releaseConnection(connection);
? ? connection = null;
? ? if (jre instanceof JedisAskDataException) {
? ? ? asking = true;
? ? ? askConnection.set(this.connectionHandler.getConnectionFromNode(jre.getTargetNode()));
? ? } else if (jre instanceof JedisMovedDataException) {
? ? } else {
? ? ? throw new JedisClusterException(jre);
? ? }
? ? return runWithRetries(key, attempts - 1, false, asking);
? } finally {
? ? releaseConnection(connection);
? }
}
首先注意看第21行代碼,這里是表示根據(jù)key的hash值,計(jì)算出來(lái)slot,然后根據(jù)slot信息獲取相應(yīng)的節(jié)點(diǎn)ip和端口信息,獲取具體IP的代碼邏輯在redis.clients.jedis.JedisSlotBasedConnectionHandler.getConnectionFromSlot這個(gè)方法中,具體代碼如下:
public Jedis getConnectionFromSlot(int slot) {
? ? JedisPool connectionPool = cache.getSlotPool(slot);
? ? if (connectionPool != null) {
? ? ? // It can't guaranteed to get valid connection because of node
? ? ? // assignment
? ? ? return connectionPool.getResource();
? ? } else {
? ? ? renewSlotCache(); //It's abnormal situation for cluster mode, that we have just nothing for slot, try to rediscover state
? ? ? connectionPool = cache.getSlotPool(slot);
? ? ? if (connectionPool != null) {
? ? ? ? return connectionPool.getResource();
? ? ? } else {
? ? ? ? //no choice, fallback to new connection to random node
? ? ? ? return getConnection();
? ? ? }
? ? }
? }
}
這個(gè)代碼邏輯比較簡(jiǎn)單,首先是從緩存獲取,緩存的數(shù)據(jù)結(jié)構(gòu)是個(gè)map對(duì)象,map對(duì)象用了一個(gè)最簡(jiǎn)單直接的方法,存儲(chǔ)了16384對(duì)象信息,key分別是對(duì)應(yīng)的0-16383個(gè)數(shù)字,value就是JedisPool對(duì)象,也就是保存的具體的服務(wù)器IP和端口。如果緩存沒(méi)有獲取到,執(zhí)行第8行代碼,加載信息,加載到緩存以后,如果依然沒(méi)有獲取到,那就返回一個(gè)隨機(jī)的,理論上應(yīng)該都是能獲取到的,當(dāng)然也不排除極端的情況,比如訪問(wèn)其中一個(gè)master節(jié)點(diǎn)掛機(jī),redis.clients.jedis.JedisClusterCommand.runWithRetries這個(gè)方法會(huì)拋出一個(gè)異常JedisConnectionException,但是這個(gè)異常里面會(huì)遞歸調(diào)用多次,也就是說(shuō)會(huì)默認(rèn)重試調(diào)用,默認(rèn)的次數(shù)是5次,當(dāng)最后一次調(diào)用的時(shí)候,依然報(bào)了這個(gè)異常,那么就會(huì)重新加載redis的集群信息,因?yàn)閙aster掛機(jī)以后,新的slave產(chǎn)生,slots對(duì)應(yīng)的IP信息也會(huì)出現(xiàn)變化。
redis集群中的一個(gè)master掛機(jī)以后,新的slave晉升為master,這中間有個(gè)心跳檢查時(shí)間,根據(jù)redis的參數(shù)cluster-slave-validity-factor配置,在這個(gè)時(shí)間內(nèi),如果獲取掛機(jī)master實(shí)例上的數(shù)據(jù),將會(huì)頻繁報(bào)錯(cuò),通常在應(yīng)用場(chǎng)景中,就會(huì)穿透緩存層,直接訪問(wèn)數(shù)據(jù)庫(kù)。因?yàn)槭莚edis集群,每個(gè)master上面分配的數(shù)據(jù)都只是一部分,即便是穿透緩存層,也是一部分?jǐn)?shù)據(jù)而已,而且根據(jù)我們部署的redis集群的數(shù)量,redis master實(shí)例越多,數(shù)據(jù)分配的越是均勻,故障的發(fā)生率越是低,影響的面就越小,這樣redis集群就能很好的保證我們服務(wù)的高可用性。
Redis集群擴(kuò)容
redis集群的擴(kuò)容和縮容,同樣使用redis-trib來(lái)操作,下面是操作執(zhí)行流程,執(zhí)行記錄比較多,而且比較長(zhǎng),可以直接跳過(guò),看后面操作命令的總結(jié),實(shí)際操作時(shí),有問(wèn)題再看具體的執(zhí)行流程記錄:
## 新增加一個(gè)master節(jié)點(diǎn)
ruby redis-trib.rb add-node 192.168.35.73:9003 192.168.35.74:9002
>>> Adding node 192.168.35.73:9003 to cluster 192.168.35.74:9002
>>> Performing Cluster Check (using node 192.168.35.74:9002)
S: 82da7bd42cdd96785a2f131445c7b189c48c75a3 192.168.35.74:9002
? slots: (0 slots) slave
? replicates c0be24752e6a23b566112c5389c20c35e97a5182
S: e00b99df51149512a4b4e6d64eec4d7550a63ede 192.168.35.73:9002
? slots: (0 slots) slave
? replicates 7a70746b2e23ee06e1bedb07f1952bfc9501a859
M: 7a70746b2e23ee06e1bedb07f1952bfc9501a859 192.168.35.66:7001
? slots:0-5460 (5461 slots) master
? 1 additional replica(s)
M: c1e9e762e553b5b62a674c439c8272447b2efc82 192.168.35.73:7001
? slots:5461-10922 (5462 slots) master
? 1 additional replica(s)
S: 899a7a0199eeab0fcc5bce108efc2a57cf3d1d23 192.168.35.66:9002
? slots: (0 slots) slave
? replicates c1e9e762e553b5b62a674c439c8272447b2efc82
M: c0be24752e6a23b566112c5389c20c35e97a5182 192.168.35.74:7001
? 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.
>>> Send CLUSTER MEET to node 192.168.35.73:9003 to make it join the cluster.
[OK] New node added correctly.
以上記錄很多,但是實(shí)際上操作步驟沒(méi)有多少,這里總結(jié)一下:
##第一個(gè)命令,首先是增加一個(gè)master實(shí)例,第一個(gè)IP:PORT信息是需要新增的實(shí)例地址,后面的IP:PORT是集群中任意一個(gè)實(shí)例的端口和ip信息,就是集群的入口。
ruby redis-trib.rb add-node 192.168.35.73:9003 192.168.35.74:9002
##第二個(gè)命令,這個(gè)命令就是為剛才新增的那個(gè)master增加一個(gè)slave實(shí)例,注意--slave參數(shù)表示增加的是slave實(shí)例,master-id就是剛才增加的master的node id值,可以通過(guò)check查看。第一個(gè)IP:PORT信息就是新增的slave實(shí)例信息,第二個(gè)參數(shù)和第一個(gè)命令一樣,就是告訴集群的入口。
ruby redis-trib.rb add-node --slave --master-id 67d82f2e6e1f9c0afbc15090732d7f2f41064fbc 192.168.35.73:9004 192.168.35.74:9002
##第三個(gè)命令,新增的實(shí)例信息,其實(shí)是沒(méi)有分配slot值的,即便是執(zhí)行rebalance也是沒(méi)有值的,就是認(rèn)為該實(shí)例還沒(méi)有啟用,所以需要執(zhí)行一下,給他分配一些slots值過(guò)去。reshard就是slots遷移命令,from和to 分別表示從哪里遷移到目標(biāo)實(shí)例。如果我們需要下掉某一個(gè)master實(shí)例,我們就可以通過(guò)這個(gè)操作把當(dāng)前實(shí)例的所有slots值全部遷移走。
ruby redis-trib.rb reshard --from e00b99df51149512a4b4e6d64eec4d7550a63ede --to 67d82f2e6e1f9c0afbc15090732d7f2f41064fbc --slots 3099 --yes --timeout 30 192.168.35.74:9002
##最后一步命令是可選的,因?yàn)槟闶謩?dòng)遷移的slots值,其實(shí)是不夠均衡的,所以對(duì)于強(qiáng)迫癥的用戶來(lái)說(shuō),必須要執(zhí)行一下rebalance命令,然后系統(tǒng)會(huì)重新分配slots信息,均勻分配
ruby redis-trib.rb rebalance 192.168.35.74:9002
以上操作對(duì)于應(yīng)用程序來(lái)說(shuō)都是無(wú)感知的,除非是遷移的時(shí)候搞down機(jī)了,應(yīng)用程序會(huì)報(bào)錯(cuò),但是報(bào)錯(cuò)的范圍也會(huì)很小。
總結(jié)
Redis Cluster方案,適合高并發(fā)讀寫的場(chǎng)景,無(wú)中心化的配置,保障集群的高可用性,并且通過(guò)指定多個(gè)slave的方式,保障了數(shù)據(jù)的安全性,而且提供了相對(duì)簡(jiǎn)單的集群管理配置,沒(méi)有三方服務(wù)的依賴,用來(lái)構(gòu)建成產(chǎn)線緩存服務(wù)集群,再合適不過(guò)。