Redis集群搭建,扩容及收缩节点

简单介绍

1.redis集群
Redis Cluster 是 redis的分布式解决方案,在3.0版本正式推出,当遇到单机、内存、并发、流量等瓶颈时,可以采用Cluster架构方案达到负载均衡目的。
Redis Cluster之前的分布式方案有两种:

	1)客户端分区方案: 优点分区逻辑可控,缺点是需要自己处理数据路由,高可用和故障转移等。
	2)代理方案: 优点是简化客户端分布式逻辑和升级维护便利,缺点加重架构部署和性能消耗。

官方提供的 Redis Cluster集群方案,很好的解决了集群方面的问题
2.数据分布
分布式数据库首先要解决把整个数据库集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,每个节点负责整体数据的一个子集,需要关注的是数据分片规则,Redis Cluster采用哈希分片规则。

二.集群搭建

示意图:
集群架构示意图
这里用三台服务器,每台服务器上各两个redis节点保证主从不在同一服务器上即可。

一.环境准备

redis1:192.168.1.102
redis2:192.168.1.103
redis3:192.168.1.104
关闭防火墙,selinux

二.目录规划

 redis安装目录
/opt/redis_cluster/redis_{PORT}/{conf,logs,pid}
 redis数据目录
/data/redis_cluster/redis_{PORT}/redis_{PORT}.rdb
redis运维脚本
/root/scripts/redis_shell.sh(文章末尾)

三.手动搭建部署集群

redis1操作

1.创建安装目录及数据目录(实际端口按规划部署这里以6380,6381为例 )
mkdir -p /opt/redis_cluster/redis_{6380,6381}/{conf,logs,pid}
mkdir -p /data/redis_cluster/redis_{6380,6381}

安装redis可参考我上一篇文章这里不再赘述
2.配置文件的小脚本

#!/bin/bash
cat >/opt/redis_cluster/redis_6380/conf/redis_6380.conf<<EOF
bind 192.168.1.102
port 6380
daemonize yes
pidfile "/opt/redis_cluster/redis_6380/pid/redis_6380.pid"
logfile "/opt/redis_cluster/redis_6380/logs/redis_6380.log"
dbfilename "redis_6380.rdb"
dir "/data/redis_cluster/redis_6380/"
cluster-enabled yes    
cluster-config-file nodes_6380.conf
cluster-node-timeout 15000
EOF
#创建6381配置文件 修改一下
cd /opt/redis_cluster/
cp redis_6380/conf/redis_6380.conf redis_6381/conf/redis_6381.conf
sed -i 's#6380#6381#g' redis_6381/conf/redis_6381.conf 
#启动服务
redis-server /opt/redis_cluster/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_cluster/redis_6381/conf/redis_6381.conf
3.复制redis1的安装和数据目录到redis2,redis3(可先做ssh秘钥对)
ssh-keygen -t rsa
ssh-copy-id root@192.168.1.103
ssh-copy-id root@192.168.1.104
输入root对应密码即可
scp -rp /opt/redis_cluster/ root@192.168.1.103:/opt
scp -rp /opt/redis_cluster/ root@192.168.1.104:/opt
4.redis2,3分别操作,脚本只需要把里面地址改一下
#!/bin/bash
#安装redis
cd /opt/redis_cluster/redis
make install 
#修改配置文件中的地址
find /opt/redis_cluster/redis_638* -type f -name "*.conf"|xargs sed -i "s#102#103#g"
#创建数据目录
mkdir -p /data/redis_cluster/redis_{6380,6381}
#启动两节点redis服务
redis-server /opt/redis_cluster/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_cluster/redis_6381/conf/redis_6381.conf
5.Redis Cluster 通讯流程

在分布式存储中需要提供维护节点元数据信息的机制,所谓元数据是指:节点负责哪些数据,是否出现故障灯状态信息,
redis 集群采用 Gossip(流言)协议,Gossip 协议工作原理就是节点彼此不断交换信息,一段时间后所有的节点都会知道集群完整信息,这种方式类似流言传播。
通信过程:
1)集群中的每一个节点都会单独开辟一个 Tcp 通道,用于节点之间彼此通信,防火墙放行(端口号+10000).
2)每个节点在固定周期内通过特定规则选择结构节点发送 ping 消息
3)接收到 ping 消息的节点用 pong 消息作为响应。集群中每个节点通过一定规则挑选要通信的节点,每个节点可能知道全部节点,也可能仅知道部分节点,只要这些节点彼此可以正常通信,最终他们会打成一致的状态,当节点出现故障,新节点加入,主从角色变化等,它能够给不断的ping/pong消息,从而达到同步目的。
通讯消息类型:
Gossip
Gossip 协议职责就是信息交换,信息交换的载体就是节点间彼此发送Gossip 消息。
常见 Gossip 消息分为:ping、 pong、 meet、 fail 等

meet 消息:用于通知新节点加入,消息发送者通知接受者加入到当前集群,meet 消息通信正常完成后,接收节点会加入到集群中并进行ping、 pong 消息交换

ping 消息:集群内交换最频繁的消息,集群内每个节点每秒想多个其他节点发送 ping 消息,用于检测节点是否在线和交换彼此信息。

Pong 消息:当接收到 ping,meet 消息时,作为相应消息回复给发送方确认消息正常通信,节点也可以向集群内广播自身的 pong 消息来通知整个集群对自身状态进行更新。

fail 消息:当节点判定集群内另一个节点下线时,回向集群内广播一个fail 消息,其他节点收到 fail 消息之后把对应节点更新为下线状态。
6.手动配置节点发现

当把所有节点都启动后查看进程会有cluster的字样

但是登录后执行CLUSTER NODES命令会发现只有每个节点自己的ID,目前集群内的节点还没有互相发现,所以搭建redis集群我们第一步要做的就是让集群内的节点互相发现.
在执行节点发现命令之前我们先查看一下集群的数据目录会发现有生成集群的配置文件

查看后发现只有自己的节点内容,等节点全部发现后会把所发现的节点ID写入这个文件

集群模式的Redis除了原有的配置文件之外又加了一份集群配置文件.当集群内节点
信息发生变化,如添加节点,节点下线,故障转移等.节点会自动保存集群状态到配置文件.
需要注意的是,Redis自动维护集群配置文件,不需要手动修改,防止节点重启时产生错乱.

节点发现使用命令:

CLUSTER MEET {IP} {PORT}

提示:在集群内任意一台机器执行此命令就可以

[root@redis1 ~]# sh redis_shell.sh login 6380
192.168.1.102:6380> CLUSTER MEET 192.168.1.102 6381
OK
192.168.1.102:6380> CLUSTER MEET 192.168.1.103 6380
OK
192.168.1.102:6380> CLUSTER MEET 192.168.1.104 6380
OK
192.168.1.102:6380> CLUSTER MEET 192.168.1.103 6381
OK
192.168.1.102:6380> CLUSTER MEET 192.168.1.104 6381
OK
192.168.1.102:6380> CLUSTER NODES
d03cb38d612802aead8f727b1726a3359c241818 192.168.1.102:6380 myself,master - 0 0 4 connected
67c8128df00b2fa304a41bafbadac25a654f196d 192.168.1.102:6381 master - 0 1562059947079 1 connected
a23ec7d444791a0b258ac454ef15cb4d6ab5abd2 192.168.1.104:6381 master - 0 1562059948087 5 connected
e57807d4d35daaaca05f4a9705e844eab15c7ce8 192.168.1.103:6381 master - 0 1562059949098 0 connected
aa9da67a594dfb357195f12ca4c44001804ee470 192.168.1.104:6380 master - 0 1562059945063 3 connected
5cb6895305520e6a0aa4198a6ea5f2c087530b41 192.168.1.103:6380 master - 0 1562059950108 2 connected

节点都发现完毕后我们再次查看集群配置文件
可以看到,发现到的节点的ID也被写入到了集群的配置文件里.

7.Redis Cluster手动分配槽位

虽然节点之间已经互相发现了,但是此时集群还是不可用的状态,因为并没有给节点分配槽位,而且必须是所有的槽位都分配完毕后整个集群才是可用的状态.反之,也就是说只要有一个槽位没有分配,那么整个集群就是不可用的.前面说了,我们虽然有6个节点,但是真正负责数据写入的只有3个节点,其他3个节点只是作为主节点的从节点,也就是说,只需要分配期中三个节点的槽位就可以了
分配槽位的方法:
分配槽位需要在每个主节点上来配置,此时有2种方法执行:

	分别登录到每个主节点的客户端来执行命令
	在其中一台机器上用redis客户端远程登录到其他机器的主节点上执行命令

每个节点执行命令:槽位总数为16383个,合理分配即可。

[root@redis1 ~]# redis-cli -h 192.168.1.102 -p 6380 cluster addslots {0..5461}
OK
[root@redis1 ~]# redis-cli -h 192.168.1.103 -p 6380 cluster addslots {5462..10922}
OK
[root@redis1 ~]# redis-cli -h 192.168.1.104 -p 6380 cluster addslots {10923..16383}
OK

分配完所有槽位之后我们再查看一下集群的节点状态和集群状态可以看到三个节点都分配了槽位,而且集群的状态是OK的.

8.手动配置集群高可用

虽然这时候集群是可用的了,但是整个集群只要有一台机器坏掉了,那么整个集群都是不可用的.
所以这时候需要用到其他三个节点分别作为现在三个主节点的从节点,以应对集群主节点故障时可以进行自动切换以保证集群持续可用.
注意:
1.不要让复制节点复制本机器的主节点, 因为如果那样的话机器挂了集群还是不可用状态, 所以复制节点要复制其他服务器的主节点.
2.使用redis-trid工具自动分配的时候会出现复制节点和主节点在同一台机器上的情况,需要注意

(5)测试集群
这一次我们采用在一台机器上使用redis客户端远程操作集群其他节点
注意:
1.需要执行命令的是每个服务器的从节点
2.注意主从的ID不要搞混了.
格式为

```
redis-cli -h 从服务器ip -p 端口号 cluster replicate 主服务器redis的id号

[root@redis1 ~]# redis-cli -h 192.168.1.103 -p 6381 CLUSTER REPLICATE d03cb38d612802aead8f727b1726a3359c241818  (102主机6380的id)
OK
[root@redis1 ~]# redis-cli -h 192.168.1.104 -p 6381 CLUSTER REPLICATE 5cb6895305520e6a0aa4198a6ea5f2c087530b41 (103主机6380的id)
OK
[root@redis1 ~]# redis-cli -h 192.168.1.102 -p 6381 CLUSTER REPLICATE aa9da67a594dfb357195f12ca4c44001804ee470  (104主机6380的id)
OK
9.Redis Cluster测试集群

我们使用常规插入redis数据的方式往集群里写入数据看看会发生什么

[root@redis1 ~]# redis-cli -h redis1 -p 6380 set k1 v1
(error) MOVED 12706 192.168.1.10:6380
结果提示error, 但是给出了集群另一个节点的地址
那么这条数据到底有没有写入呢? 我们登录这两个节点分别查看

[root@redis1 ~]# redis-cli -h redis3 -p 6380 get k1
(nil)
结果没有,这是因为使用集群后由于数据被分片了,所以并不是说在那台机器上写入数据就会在哪台机器的节点上写入,
集群的数据写入和读取就涉及到了另外一个概念,ASK路由

(7).Redis Cluster ASK路由介绍
在集群模式下,Redis接受任何键相关命令时首先会计算键对应的槽,再根据槽找出所对应的节点
如果节点是自身,则处理键命令;
否则回复MOVED重定向错误,通知客户端请求正确的节点,这个过程称为Mover重定向.
知道了ask路由后,我们使用-c选项批量插入一些数据

[root@redis1 ~]# cat input_key.sh 
#!/bin/bash
for i in $(seq 1 1000)
do
    redis-cli -c -h 192.168.1.102 -p 6380 set k_${i} v_${i} && echo "set k_${i} is ok"
done

写入后我们同样使用-c选项来读取刚才插入的键值,然后查看下redis会不会帮我们路由到正确的节点上

[root@redis1 ~]# redis-cli -c -h redis1 -p 6380 
redis1:6380> get k_1
"v_1"
redis1:6380> get k_100
-> Redirected to slot [5541] located at 192.168.1.103:6380
"v_100"
192.168.1.103:6380> get k_1000
-> Redirected to slot [79] located at 192.168.1.102:6380
"v_1000"
10.模拟故障转移

至此,我们已经手动的把一个redis高可用的集群部署完毕了, 但是还没有模拟过故障
这里我们就模拟故障,停掉期中一台主机的redis节点,然后查看一下集群的变化
我们使用暴力的kill -9(真实环境禁止使用,建议使用kill或pkill)杀掉 redis2上的redis集群节点,然后观察节点状态
理想情况应该是redis3上的6381从节点升级为主节点
在redis1上查看集群节点状态
虽然我们已经测试了故障切换的功能,但是节点修复后还是需要重新上线
所以这里测试节点重新上线后的操作
重新启动redis2的6380,然后观察日志
观察redis1上的日志
这时假如我们想让修复后的节点重新上线,可以在想变成主库的从库执行CLUSTER FAILOVER命令
这里我们在redis2的6380上执行
操作命令:

中止redis2的服务:pkill redis-server
查看日志:sh redis_shell.sh tail 6380
中断服务后可以让子弹飞一会

再启动redis2的服务
redis2重回master:

redis-cli  -h 192.168.1.103 -p  6380 CLUSTER FAILOVER

三.使用工具自动搭建redis cluster

手动搭建集群便于理解集群创建的流程和细节,不过手动搭建集群需要很多步骤,当集群节点众多时,必然会加大搭建集群的复杂度和运维成本。
较老版本官方提供了 redis-trib.rb的工具方便我们快速搭建集群。redis-trib.rb是采用 Ruby 实现的 redis 集群管理工具,内部通过 Cluster相
关命令帮我们简化集群创建、检查、槽迁移和均衡等常见运维操作,使用前要安装 ruby 依赖环境。
较新版本直接用就行
前提准备:
(1)停掉所有的节点,然后清空数据,恢复成一个全新的集群,所有机器执行命令

pkill redis
rm -rf /data/redis_cluster/redis_6380/*
rm -rf /data/redis_cluster/redis_6381/*

(2)全部清空之后启动所有的节点,所有机器执行

redis-server 
/opt/redis_cluster/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_cluster/redis_6381/conf/redis_6381.conf

(3)安装命令:注意新版本redis不需安装,直接采用步骤(4)

yum makecache fast
yum install rubygems
gem sources --remove https://rubygems.org/
gem sources -a http://mirrors.aliyun.com/rubygems/
gem update –system
gem install redis -v 3.3.5


redis1执行创建集群命令
cd /opt/redis_cluster/redis/src/
./redis-trib.rb create --replicas 1 192.168.1.102:6380 192.168.1.103:6380 192.168.1.103:6380 192.168.1.102:6381 192.168.1.104:6381 192.168.1.104:6381

检查集群完整性
./redis-trib.rb check 192.168.1.102:6380

(4)或直接使用redis-cli命令*****

创建群集:
redis-cli --cluster create --cluster-replicas 1 192.168.129.222:6380 192.168.129.154:6380 192.168.129.223:6380 192.168.129.222:6381 192.168.129.154:6381 192.168.129.223:6381 

检查完整性:
redis-cli --cluster check 192.168.1.102:6380

四.扩容及收缩节点

1.扩容

Redis集群的扩容操作可分为以下几个步骤
1)准备新节点
2)加入集群
3)迁移槽和数据
扩容流程图:

我们在redis1上创建2个新节点

mkdir -p /opt/redis_cluster/redis_{6390,6391}/{conf,logs,pid}
mkdir -p /data/redis_cluster/redis_{6390,6391}
cd /opt/redis_cluster/
cp redis_6380/conf/redis_6380.conf redis_6390/conf/redis_6390.conf
cp redis_6380/conf/redis_6380.conf redis_6391/conf/redis_6391.conf
sed -i 's#6380#6390#g' redis_6390/conf/redis_6390.conf
sed -i 's#6380#6391#g' redis_6391/conf/redis_6391.conf
启动节点
bash redis_shell.sh start 6390
bash redis_shell.sh start 6391

发现节点
redis-cli -c -h redis1 -p 6380 cluster meet 192.168.1.102 6390
redis-cli -c -h redis1 -p 6380 cluster meet 192.168.1.102 6391

确定主从
redis-cli -h 192.168.1.102 -p 6391 cluster replicate 6390的id号

在redis1上使用工具扩容:注意新版本使用步骤
1.将节点加入群集
(1)旧版本3…

cd /opt/redis_cluster/redis/src/
./redis-trib.rb add-node 192.168.1.102:6390 192.168.1.102:6380
./redis-trib.rb add-node 192.168.1.102:6390 192.168.1.102:6380
./redis-trib.rb reshard 192.168.1.102:6380

(2)或直接使用哦redis-cli命令完成
	redis-cli --cluster add-node 192.168.1.102:6390 192.168.1.102:6380
	redis-cli --cluster add-node 192.168.1.102:6391 192.168.1.102:6380

2.给6390分配槽

老版:
/bin/redis-trib.rb reshard 192.168.1.102:6390
新版: 
redis-cli --cluster reshard 192.168.1.102:6390

打印出进群每个节点信息后,reshard命令需要确认迁移的槽数量,这里我们输入4096个:
How many slots do you want to move (from 1 to 16384)? 4096
输入6390的节点ID作为目标节点,也就是要扩容的节点,目标节点只能指定一个
What is the receiving node ID? 6390的ID号
之后输入源节点的ID,这里分别输入每个主节点的6380的ID最后输入done,或者直接输入all
Source node #1:all
迁移完成后命令会自动退出,这时候我们查看一下集群的状态

./redis-trib.rb rebalance 192.168.1.102:6380  #旧版本
或
redis-cli --cluster rebalance 192.168.1.102:6380  #新版本
2.收缩节点

流程说明
1).首先需要确定下线节点是否有负责的槽,
如果是,需要把槽迁移到其他节点,保证节点下线后整个集群槽节点映射的完整性.
2).当下线节点不再负责槽或者本身是从节点时,
就可以通知集群内其他节点忘记下线节点,当所有的节点忘记该节点后可以正常关闭.

这里我们准备将刚才新添加的节点下线,也就是6390和6391
收缩和扩容迁移的方向相反,6390变为源节点,其他节点变为目标节点,源节点把自己负责的4096个槽均匀的迁移到其他节点上,.
由于redis-trib…rb reshard命令只能有一个目标节点,因此需要执行3次reshard命令,分别迁移1365,1365,1366个槽.
操作命令:

老:
./redis-trib.rb reshard 192.168.1.102:6390
新:
redis-cli --cluster reshard 192.168.1.102:6390
How many slots do you want to move (from 1 to 16384)? 1365
What is the receiving node ID? 其余三台6380的ID号分三次依次输入
Source node #1:输入6390的id
done

忘记节点
由于我们的集群是做了高可用的,所以当主节点下线的时候从节点也会顶上,所以最好我们先下线从节点,然后在下线主节点

老:
cd /opt/redis_cluster/redis/src/
./redis-trib.rb del-node 192.168.1.102:6391 ID
./redis-trib.rb del-node 192.168.1.102:6390 ID
新:
redis-cli --cluster del-node 192.168.1.102:6391 ID号
redis-cli --cluster del-node 192.168.1.102:6390 ID号
redis_shell.sh
#!/bin/bash

USAG(){
    echo "sh $0 {start|stop|restart|login|ps|tail} PORT"
}
if [ "$#" = 1 ]
then
    REDIS_PORT='6379'
elif 
    [ "$#" = 2 -a -z "$(echo "$2"|sed 's#[0-9]##g')" ]
then
    REDIS_PORT="$2"
else
    USAG
    exit 0
fi

REDIS_IP=$(hostname -I|awk '{print $1}')
PATH_DIR=/opt/redis_cluster/redis_${REDIS_PORT}/
PATH_CONF=/opt/redis_cluster/redis_${REDIS_PORT}/conf/redis_${REDIS_PORT}.conf
PATH_LOG=/opt/redis_cluster/redis_${REDIS_PORT}/logs/redis_${REDIS_PORT}.log

CMD_START(){
    redis-server ${PATH_CONF}
}

CMD_SHUTDOWN(){
    redis-cli -c -h ${REDIS_IP} -p ${REDIS_PORT} shutdown
}

CMD_LOGIN(){
    redis-cli -c -h ${REDIS_IP} -p ${REDIS_PORT}
}

CMD_PS(){
    ps -ef|grep redis
}

CMD_TAIL(){
    tail -f ${PATH_LOG}
}

case $1 in
    start)
        CMD_START
        CMD_PS
        ;;
    stop)
        CMD_SHUTDOWN
        CMD_PS
        ;;
    restart)
        CMD_START
        CMD_SHUTDOWN
        CMD_PS
        ;;
    login)
        CMD_LOGIN
        ;;
    ps)
        CMD_PS
        ;;
    tail)
        CMD_TAIL
        ;;
    *)
        USAG
esac
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值