1 redis集群
1.1 redis集群简介
在redis3.0
以前,提供了Sentinel
工具来监控各Master
的状态,如果Master
异常,则会做主从切换,将slave
作为master
,同时把master
作为slave
。其配置也是稍微的复杂,并且各方面表现一般。在redis3.0
以后,redis
已经支持集群的容错功能,并且非常简单
一主一备模式:给每个业务单元创建一个备份业务单元,原来的业务单元(master
)后产生的叫做(slave
)
集群和伪集群:每个业务单元都安装到单独的服务器上是集群;所有的业务单元都安装到同一个服务器上,通过端口区分不同的业务单元
1.1.1 Redis集群数据共享
1.1.1.1 分片哈希槽
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
就可以了。
因为将一个哈希槽从一个节点移动到另一个节点不会造成节点阻塞, 所以无论是添加新节点还是移除已存在节点, 又或者改变某个节点包含的哈希槽数量, 都不会造成集群下线
1.1.1.2 客户端如何重定向哈希槽
新增节点或者重新分配 slots
导致 slots
与节点之间的映射关系改变了,客户端如何知道把请求发到哪里
Redis Cluster
提供了请求重定向机制解决:客户端将请求发送到某个节点上,这个节点没有相应的数据,该 Redis
节点会告诉客户端将请求发送到其他的节点。
在 Redis cluster
模式下,节点对请求的处理过程如下:
- 通过哈希槽映射,检查当前
Redis key
是否存在当前节点 - 若哈希槽不是由自身节点负责,就返回
MOVED
重定向 - 若哈希槽确实由自身负责,且
key
在slot
中,则返回该key对应结果 - 若
Redis key
不存在此哈希槽中,检查该哈希槽是否正在迁出(MIGRATING)? - 若
Redis key
正在迁出,返回ASK错误重定向客户端到迁移的目的服务器上 - 若哈希槽未迁出,检查哈希槽是否导入中?
- 若哈希槽导入中且有
ASKING
标记,则直接操作,否则返回MOVED
重定向
1.1.1.2.1 Moved 重定向
客户端给一个Redis实例
发送数据读写操作时,如果计算出来的槽不是在该节点上,这时候它会返回MOVED
重定向错误,MOVED
重定向错误中,会将哈希槽所在的新实例的IP和port
端口带回去,并且客户端会更新本地 slots
与节点映射关系,以便下次可以正确访问。这就是Redis Cluster
的MOVED
重定向机制。
流程图如下:
1.1.1.2.2 ASK 重定向
Ask重定向
一般发生于集群伸缩的时候。集群伸缩会导致槽迁移,当我们去源节点访问时,此时数据已经可能已经迁移到了目标节点,使用Ask重定向
可以解决此种情况。
如果某个 slot
的数据只有部分迁移过去,没有迁移完成,节点收到客户端请求如果能根据 key -> slot -> node
映射关系定位到的节点存在该 key
,则直接执行命令,否则就向客户端响应 ASK
错误,表示该 key
所在的 slot
正在迁移到其他节点,客户端先给目标节点发送 ASKING
命令询问节点是否可以处理,接着才会发送操作指令。
注意
:ASK
错误指令并不会更新客户端缓存的 slot
分配信息。
1.1.1.3 为什么集群的 slots 是 16384
CRC16
算法,产生的 hash
值有 16 bit
位,可以产生 65536(2^16)
个值 ,也就是说值分布在 0 ~ 65535
之间,为什么不用65535而是16384呢:
- 正常的 ping 数据包携带节点的完整配置,用的是一个 bitmap 数据结构,它能以幂等方式来更新配置。如果采用 16384 个插槽,占空间 2KB (16384/8(一个字节8bit)/1024(1024个字节1kB));如果采用 65536 个插槽,占空间 8KB (65536/8(一个字节8bit)/1024(1024个字节1kB))。
8KB 的心跳包看似不大,但是这个是心跳包每秒都要将本节点的信息同步给集群其他节点。比起 16384 个 slot ,header 大小增加了 4 倍,ping 消息的消息头太大了,浪费带宽。 - Redis Cluster 不太可能扩展到超过 1000 个主节点,太多可能导致网络拥堵。
-
16384
个 slot 范围比较合适,当集群扩展到1000
个节点时,也能确保每个master
节点有足够的 slot。
1.1.2 Redis集群中的主从复制
为了使得集群在一部分节点下线或者无法与集群的大多数节点进行通讯的情况下, 仍然可以正常运作, 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
集群还是会停止运作
1.1.3 Redis 集群的一致性保证
Redis
集群不保证数据的强一致性(strong consistency
): 在特定条件下, Redis
集群可能会丢失已经被执行过的写命令
使用异步复制(asynchronous replication
)是 Redis 集群
可能会丢失写命令的其中一个原因。 考虑以下这个写命令的例子:
主节点 B
执行写命令,并向客户端返回命令回复
主节点 B
将刚刚执行的写命令复制给它的从节点 B1
、 B2
和 B3
如你所见, 主节点对命令的复制工作发生在返回命令回复之后, 因为如果每次处理命令请求都需要等待复制操作完成的话, 那么主节点处理命令请求的速度将极大地降低 —— 必须在性能和一致性之间做出权衡。
Redis
集群另外一种可能会丢失命令的情况如下例:
假设集群包含 A 、 B 、 C 、 A1 、 B1 、 C1
六个节点, 其中A 、B 、C
为主节点, 而 A1 、B1 、C1
分别为三个主节点的从节点, 另外还有一个客户端 Z1
假设集群中发生网络分裂, 那么集群可能会分裂为两方, 大多数(majority
)的一方包含节点 A 、C 、A1 、B1 和 C1 , 而少数(minority
)的一方则包含节点 B 和客户端 Z1 。这时候分裂的两方是互相不通的,即:A、C 等会认为 B 已经下线,且客户端 Z1
只能和 B
连通
在网络分裂期间, 主节点 B
仍然会接受 Z1
发送的写命令;如果网络分裂出现的时间很短, 那么集群会继续正常运行;
但是, 如果网络分裂出现的时间足够长, 使得大多数一方将从节点 B1
设置为新的主节点, 并使用 B1
来代替原来的主节点 B
, 那么 Z1
发送给主节点 B
的写命令将丢失。
注意:
在网络分裂出现期间, 客户端 Z1
可以向主节点 B
发送写命令的最大时间是有限制的, 这一时间限制称为节点超时时间(node timeout
), 是 Redis
集群的一个重要的配置选项:
对于大多数一方来说, 如果一个主节点未能在节点超时时间所设定的时限内重新联系上集群, 那么集群会将这个主节点视为下线, 并使用从节点来代替这个主节点继续工作。
对于少数一方, 如果一个主节点未能在节点超时时间所设定的时限内重新联系上集群, 那么它将停止处理写命令, 并向客户端报告错误
另注意:
redis
搭建集群后就不存在所谓的分区概念了(即所谓的0~15
分区),集群搭建后就都是默认的db0
了
1.1.4 节点选举
Redis
多主多从模式下,如果一个服务器节点中的主节点挂掉了,就需要选出从节点
选举条件:
- 节点是已下线
Master
对应的Slave
-
FAIL
状态的Master
负责的hash slot
非空 - 主从节点之间的
replication link
断线的时长不能超过NODE_TIMEOUT * REDIS_CLUSTER_SLAVE_VALIDITY_MULT
当slave
发现自己的master
变为FAIL
状态时,便尝试进行Failover
,以期成为新的master
。由于挂掉的master
可能会有多个slave
,从而存在多个slave
竞争成为master
节点的过程, 其过程如下:
-
slave
发现自己的master
变为FAIL
- 发起选举前,
slave
先给自己的epoch
(即currentEpoch
)增一,然后请求其它master
给自己投票。slave
是通过广播FAILOVER_AUTH_REQUEST
包给集中的每一个masters
-
slave
发起投票后,会等待至少两倍NODE_TIMEOUT
时长接收投票结果,不管NODE_TIMEOUT
何值,也至少会等待2秒
-
master
接收投票后给slave
响应FAILOVER_AUTH_ACK
,并且在(NODE_TIMEOUT*2
)时间内不会给同一master
的其它slave
投票 - 如果
slave
收到FAILOVER_AUTH_ACK
响应的epoch
值小于自己的epoch
,则会直接丢弃。一旦slave
收到多数master
的FAILOVER_AUTH_ACK
,则声明自己赢得了选举。 - 如果
slave
在两倍的NODE_TIMEOUT
时间内(至少2秒)未赢得选举,则放弃本次选举,然后在四倍NODE_TIMEOUT
时间(至少4秒)后重新发起选举
从节点并不是在主节点一进入 FAIL
状态就马上尝试发起选举,而是有一定延迟,一定的延迟确保我们等待FAIL
状态在集群中传播,slave
如果立即尝试选举,其它masters
或许尚未意识到FAIL状态,可能会拒绝投票。
延迟计算公式: DELAY = 500ms + random(0 ~ 500ms) + SLAVE_RANK * 1000ms
SLAVE_RANK表示此slave已经从master复制数据的总量的rank。Rank越小代表已复制的数据越新。这种方式下,持有最新数据的slave将会首先发起选举(理论上)
之所以强制延迟至少0.5秒
选举,是为确保master
的fail
状态在整个集群内传开,否则可能只有小部分master
知晓,而master
只会给处于fail
状态的master
的slaves
投票。如果一个slave
的master
状态不是fail
,则其它master
不会给它投票,Redis
通过八卦协议(即Gossip
协议,也叫谣言协议)传播fail
。而在固定延迟上再加一个随机延迟,是为了避免多个slaves
同时发起选举
1.1.5 集群各个节点之间是如何通信
通过 Gossip
协议进行通信,节点之间不断交换信息,交换的信息包括节点出现故障、新节点加入、主从节点变更, slots 信息变更等。
Gossip
协议(谣言传播协议
)基本思想:一个节点想要分享一些信息给网络中的其他的一些节点。于是,它周期性的随机选择一些节点,并把信息传递给这些节点。这些收到信息的节点接下来会做同样的事情,即把这些信息传递给其他一些随机选择的节点。一般而言,信息会周期性的传递给N个目标节点,而不只是一个。这个N被称为fanout
每个节点是通过 集群总线(cluster bus)
与其他的节点进行通信的。通讯时,使用特殊的端口号,即对外服务端口号加10000。例如如果某个node的端口号是6379,那么它与其它nodes通信的端口号是 16379。nodes 之间的通信采用特殊的二进制协议。
常用的 Gossip 消息分为 4 种,分别是:ping、pong、meet、fail
。
-
meet 消息
:通知新节点加入。消息发送者通知接受者加入当前集群,meet消息通信正常完成后,接收节点会加入到集群中并进行周期性的ping、pong消息交换。 -
ping消息
:每个节点每秒向其他节点发送 ping 消息,消息中带有自己已知的两个节点的地址、槽、状态信息、最后一次通信时间等,用于检测节点在线和交换刺激状态信息。 -
pong消息
:节点接受到ping、meet
消息后,作为响应消息回复发送方确认正常,同时 pong 还包含了自身的状态数据,向集群广播 pong 消息来通知集群自身状态进行更新。 -
fail消息
:当节点判定集群内另一个节点下线时,会向集群内广播一个fail消息,其他节点接收到fail消息之后把对应节点更新为下线状态。
1.1.6 故障转移
Redis Cluster 如何实现自动故障转移
-
故障检测
:集群中每个节点都会定期通过Gossip
协议向其他节点发送 PING 消息,检测各个节点的状态(在线状态、疑似下线状态PFAIL
、已下线状态FAIL
)。并通过 Gossip 协议来广播自己的状态以及自己对整个集群认知的改变。
通过ping/pong
消息,实现故障发现。这个环境包括主观下线和客观下线- 主观下线:某个节点认为另一个节点不可用,即下线状态,这个状态并不是最终的故障判定,只能代表一个节点的意见,可能存在误判情况。
- 客观下线:指标记一个节点真正的下线,集群内多个节点都认为该节点不可用,从而达成共识的结果。如果是持有槽的主节点故障,需要为该节点进行故障转移。
- 假如节点A标记节点B为主观下线,一段时间后,节点A通过消息把节点B的状态发到其它节点,当节点C接受到消息并解析出消息体时,如果发现节点B的pfail状态时,会触发客观下线流程;
- 当下线为主节点时,此时Redis Cluster集群为统计持有槽的主节点投票,看投票数是否达到一半,当下线报告统计数大于一半时,被标记为客观下线状态
master 选举
:使用从当前故障master
的所有slave
选举一个提升为 master。故障转移
:取消与旧 master 的主从复制关系,将旧 master 负责的槽位信息指派到当前 master,更新Cluster
状态并写入数据文件,通过gossip
协议向集群广播发送CLUSTERMSG_TYPE_PONG
消息,把最新的信息传播给其他节点,其他节点收到该消息后更新自身的状态信息或与新 master 建立主从复制关系。
1.2 redis集群准备
此处的集群搭建是在单机redis
搭建基础上建立的,此处是单机redis搭建
1.2.1 建立文件夹
由于集群搭建至少需要三个master
,因此需要六个文件夹
mkdir -p /usr/local/redis-cluster
mkdir 7001
mkdir 7002
mkdir 7003
mkdir 7004
mkdir 7005
mkdir 7006
1.2.2 修改配置文件
把之前单机的配置文件中redis.conf
分别复制到新建立的7001~7006
文件中,并对其配置文件进行修改
主要内容:
-
daemonize yes
为了后置启动 -
port
要修改为各个对应的端口号 -
bind ip
主要是当前的的机器ip
,作用是为了网络延迟而不至于有坑 -
dir /usr/local/redis-cluster/700*/
主要是指定数据文件存放位置(各个端口对应的),必须要制定不同的目录位置,不然会丢失数据 -
cluster-enabled yes
是启动集群模式 -
cluster-config-file nodes-700*.conf
此处是要和各个port
对应上的,每个节点都要配置这样的文件,把自己的配置告诉这个集群
虽然此配置的名字叫集群配置文件
,但是此配置文件不能人工编辑
,它是集群节点自动维护的文件,主要用于记录集群中有哪些节点、他们的状态以及一些持久化参数等,方便在重启时
恢复这些状态。通常是在收到请求之后这个文件就会被更新 -
cluster-node-timeout 5000
集群节点超时时间 appendonly yes
1.3 redis5之前搭建集群
redis 3.0
的集群命令也不是那么亲和,需要用ruby
编写的脚本(而且需要登录redis
客户端操作),启动、增删节点、移动槽位等。redis-5.0
以后,可以使用比较亲和的redis-cli --cluster
不需要登录客户端,直接可以进行各种操作(前提:集群模式已开启)
1.3.1 安装ruby
由于redis
集群需要使用ruby
命令,所以我们需要安装ruby
,步骤如下
yum install ruby #安装ruby
yum install rubygems #ruby的包管理器gems,运行gem文件
gem install redis #脚本需要ruby其他包,需要安装这个redis.gem
1.3.1.1 gem install redis报错
ERROR: Error installing redis:
redis requires Ruby version >= 2.3.0.
报错原因是Centos
默认支持ruby
到2.0.0
,可gem
安装redis
需要最低是2.3.0
,解决办法是先安装rvm
,再把ruby
版本提升至2.3.0
- 安装curl :
yum install curl
1.3.1.1.1 curl -L get.rvm.io | bash -s stable报错
curl
:此处的shell
脚本是放在http
页面上,不用download
,可以直接通过bash
执行
通常我们可以用curl的方式执行http
页面上的shell
脚本。 一般方式是:curl http://XXX.com/xx/xx.sh | bash
此处的选项-s
是指无名参,并传入了一个参数stable
- 报错:
curl: (7) couldn't connect to host
,把get.rvm.io
在浏览器内打开是这个地址https://raw.githubusercontent.com/rvm/rvm/master/binscripts/rvm-installer
,在浏览器中查看是访问此ip地址:185.199.109.133:443
那就用这个命令curl -L https://raw.githubusercontent.com/rvm/rvm/master/binscripts/rvm-installer | bash -s stable
- 报错:
curl: (35) SSL connect error
,因为无法在服务器使用curl
命令访问https
域名,原因是nss
版本有点旧了yum -y update nss
更新一下,重新curl
即可 - 如果以上操作还是不行的话,直接浏览器访问
get.rvm.io
,此时页面显示的是一个脚本,复制到服务器上成***.sh的可执行文件,然后执行并加参参数stable
注意:
由于后续安装rvm
很麻烦,步骤很多,若curl -L get.rvm.io
成功了可以参考Redis集群搭建
1.3.1.1.2 终极解决办法
终极解决办法:如果到最后还是gem install redis
报错,那就直接上传一个redis-3.2.1.gem
的包,然后在执行该命令gem install redis
或者gem install -l redis-3.2.1.gem
就一切迎刃而解了https://rubygems.org/downloads/redis-3.3.5.gem
1.3.2 启动6个实例
分别启动六个redis
实例,然后检查是否启动成功
/usr/local/redis/redis-server /usr/local/redis-cluster/700*/redis.conf
,此处700*
是指各个以端口命名的文件夹
使用命令:ps -ef | grep redis
查看是否启动成功
1.3.3 创建集群
此时需要到redis 3.0
的安装目录下,然后执行redis-trib.rb
命令
./redis-trib.rb create --replicas 1 192.168.2.171:7001 192.168.2.171:7002 192.168.2.171:7003 192.168.2.171:7004 192.168.2.171:7005 192.168.2.171:7006
说明:
此处的--replicas 1
是指主从节点比例,即主/从=1
那么就是主3个从3个,若主/从=2
那么就是主4个从2个
注意:
若集群无法启动,那么就删除临时的数据文件,再次重新启动每一个redis
服务,然后重新构造集群环境
1.3.4 验证集群
连接任意一个客户端即可:./redis-cli -c -h -p (-c 表示集群模式,-h指定ip地址,-p指定端口号)
例如:连接7001端口的集群/usr/local/redis/bin/redis-cli -c -h 192.18.1.171 -p 7001
验证集群,命令:cluster info (查看集群信息),cluster nodes (查看节点列表)
1.3.5 关闭集群
关闭集群时需要逐个关闭,使用连接命令加一个shutdown
即可
例如先关闭7001端口的集群:/usr/local/redis/bin/redis-cli -c -h 192.18.1.171 -p 7001 shutdown
1.4 redis5之前集群维护
1.4.1 集群信息
redis-trib.rb info命令查看集群信息
redis-trib.rb info 127.0.0.1:6383
/usr/local/ruby/lib/ruby/gems/2.5.0/gems/redis-3.3.0/lib/redis/client.rb:459: warning: constant ::Fixnum is deprecated
127.0.0.1:6380 (3b27d00d...) -> 0 keys | 5462 slots | 1 slaves.
127.0.0.1:6381 (d874f003...) -> 1 keys | 5461 slots | 1 slaves.
127.0.0.1:6379 (bc775f9c...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 1 keys in 3 masters.
0.00 keys per slot on average.
1.4.2 集群扩容
线上的集群已经有瓶颈,集群需要扩容,比如我们已经准备了一主一从(127.0.0.1:7007、127.0.0.1:7008),如下
1.4.2.1 添加主节点
添加一个主节点
redis-trib.rb add-node 127.0.0.1:7007 127.0.0.1:7001
127.0.0.1:7007
是要加的新节点,127.0.0.1:7001
是集群中已存在的任意节点
1.4.2.2 添加从节点
添加一个从节点
redis-trib.rb add-node --slave --master-id 5ef 18..17 127.0.0.1:7008 127.0.0.1:7001
--slave
指定要加的是从节点,--master-id
指定这个从节点的主节点ID,127.0.0.1:7008是需要新加的从节点,127.0.0.1:7001是集群已存在的任意节点
1.4.2.3 迁移节点
迁移一些slot给新节点
redis-trib.rb reshard 127.0.0.1:7001
1.4.3 集群缩容
上面的例子是集群扩容,相对的,由于各种原因集群可能也需要缩容,下面的例子把上文扩容的节点下线,步骤如下:
- 迁移这个节点的
slot
到其他节点(有slot
的节点是不可以直接下线的)
redis-trib.rb reshard 127.0.0.1:7001
- 查看
127.0.0.1:7001
这个maser上已经没有slot了
127.0.0.1:7001> cluster notes
1.4.3.1 下线节点(删除节点)
redis-trib.rb del-node host:port node_id
在删除节点之前,其对应的槽必须为空,所以,在进行节点删除动作之前,必须使用redis-trib.rb reshard
将其迁移出去。
需要注意的是,如果某个节点的槽被完全迁移出去,其对应的slave
也会随着更新,指向迁移的目标节点。
redis-trib.rb del-node 127.0.0.1:6379 8f7836a9a14fb6638530b42e04f5e58e28de0a6c
Removing node 8f7836a9a14fb6638530b42e04f5e58e28de0a6c from cluster 127.0.0.1:6379
/usr/local/ruby/lib/ruby/gems/2.5.0/gems/redis-3.3.0/lib/redis/client.rb:459: warning: constant ::Fixnum is deprecated
Sending CLUSTER FORGET messages to the cluster...
SHUTDOWN the node.
1.4.4 集群保证
集群中一个节点的master挂掉,从节点提升为主节点,还没有来的急给这个新的主节点加从节点,这个新的主节点就又挂掉了,那么集群中这个节点就彻底不可以用了,为了解决这个问题,我们至少保证每个节点的maser下面有两个以上的从节点,这样一来,需要的内存资源或者服务器资源就翻倍了,有没有一个折中的方法呢,答案是肯定的,cluster-migration-barrier
参数,我们只需要给集群中其中一个节点的master挂多个从库,当其他节点的master下没有可用的从库时,有多个从库的master会割让一个slave给他,保证整个集群的可用性
- 给127.0.0.1:7001 127.0.0.1:7002 这组节点下面加一个从库127.0.0.1:7003
redis-trib.rb add-node --slave --master-id 5ef 18..17 127.0.0.1:7003 127.0.0.1:7001
- 把127.0.0.1:7001 127.0.0.1:7002这组的从节点停掉
redis-cli -h 127.0.0.1 -p 7002 shutdown
- 查看127.0.0.1:7003这个节点是否成为127.0.0.1:7001的从库
cluster notes
1.5 redis5之后搭建集群
集群准备工作和之前一样,修改配置文件
redis5
之后集群搭建有两种方式:
- 一种是使用
create-cluster脚本
搭建一个机器上伪集群 - 一个是使用客户端命令
redis-cli
搭建机器
1.5.1 使用create-cluster搭建
在解压后的redis
文件夹的utils/create-cluster
路径下有一个可执行文件create-cluster
创建步骤:
- 编辑绿色的
create-cluster
可执行文件,修改里的端口,默认是30000
- 使用
./create-cluster start
命令,自动依次启动30001-30006
,六个redis实例(默认就好) - 使用
./create-cluster create
命令,自动依次创建一个redis
集群(把6个实例组合一起) - 此刻集群已经创建并准备完毕,可以发现
rdb
和aof
文件已经在当前命令执行目录自动创建
关闭步骤:
- 使用
./create-cluster stop
命令后,所有实例会自动关闭,如需重启集群,使用./create-cluster start
即可 -
./create-cluster clean
会自动移除所有的aof
日志,返还一个纯净的运行环境
create-cluster脚本
PORT=30000 集群的默认端口,这里可以不用修改
TIMEOUT=2000 超时时间,超时后集群要搞些事情,比如选举新的master
NODES=6 集群最少要求,要配置6个节点(默认即可)
REPLICAS=1 为集群中的每个主节点创建1个从节点。
在
NODES
节点是6的前提下:
如果REPLICAS=1
配置为1,意味着一个主只跟1个从(一套主从两台机器),这个集群中会有3套主从。
如果REPLICAS=2
配置为2,意味着一个主只跟2个从(一套主从三台机器),这个集群中会有2套主从。明显,集群不建议这么做,一个集群被要求最少要有3个master
注意
:在utils/create-cluster
下可执行文件create-cluster
,在执行创建集群时,依然是使用redis-cli --cluster
命令来创建的,因此有必要会使用redis-cli --cluster
1.5.2 使用redis-cli --cluster搭建集群
如果对此命令不熟悉,可以使用redis-cli --cluster help
查看集群手动创建命令的语法格式
redis-cli --cluster help 查看帮助命令
Cluster Manager Commands:
create host1:port1 ... hostN:portN 手动指定N个IP+端口
--cluster-replicas <arg> 后缀参数replicas ,指明一个主跟几个从
……
- 创建持久化目录
#cd && make -p test/cluster-test 创建持久化目录所在的根目录
#cd && cd test/cluster-test && mkdir 7000 7001 7002 7003 7004 7005 && ls 创建持久化目录
- 创建redis-server所需要的配置文件
cd 7000
vim 7000.conf 注:这个文件,是redis源码目录下redis.conf的精简版
port 7000
: 指明,用该配置文件启动的redis-server时,该服务的端口就是配置的7000
cluster-enabled yes
: 开启集群模式,允许用集群命令(redis-cli --cluster create )拉这台redis-server入伙,默认是no,关闭的
cluster-config-file nodes-7000.conf
: 集群和该服务之间的配置信息存放位置,不用理会,这个文件集群内部自己管理,自己创建、修改、更新
cluster-node-timeout 5000
: 该服务和集群失去联系的超时时间,一旦超时5秒,集群将会对该服务采取一些措施
appendonly yes
: 是否开启AOF,数据操作日志追加,默认是no(仅开启rdb)
- 把每个redis服务都要先单独启动
- 创建集群
./redis-cli
--cluster create
127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
--cluster-replicas 1 #指定每个master副本数量为1
- info命令查看集群信息
./redis-cli --cluster info 127.0.0.1:7000
1.6 集群维护
1.6.1 新增、移除节点
./redis-cli --cluster help 查看语法帮助,后面不再过多开展
……
add-node new_host:new_port existing_host:existing_port #新主机添加到集群中
--cluster-slave
--cluster-master-id <arg>
del-node host:port node_id #从集群中移除某台主机
1.6.2 槽位转移命令
edis-cli --cluster help 查看reshard槽位操作帮助
Cluster Manager Commands:
……
reshard host:port 语法格式,后面的是各个需要经过交互的确认步骤
--cluster-from <arg>
--cluster-to <arg>
--cluster-slots <arg>
--cluster-yes
--cluster-timeout <arg>
--cluster-pipeline <arg>
--cluster-replace