redis集群的搭建与管理

一、redis集群的搭建

1redis集群中的数据分布

(1)数据分区

    分布式数据库首先要解决把整个数据集按照分区规则映射到多个节点,每个节点负责整体数据的一个子集,常见的分区规则有哈希分区和顺序分区两种,常见的哈希分区规则有节点取余分区、一致性哈希分区和虚拟槽分区。Redis cluster使用的为哈希分区中的虚拟操分区。

(2)redis cluster数据分区

    Redis cluster采用虚拟槽分区,所有键根据哈希函数映射到0~16383整数槽内,计算公式为:slot=CRC16(KEY)&16383,每个节点负责维护一部分槽以及槽所映射的键值数据。

(3)redis 虚拟槽分区的特点

    1)解耦数据和节点之间的关系,简化了节点扩容和收缩难度

    2)节点自身维护槽的映射关系,不需要客户端或者代理服务维护槽分区源数据

    3)支持节点、槽、键之间的映射查询,用户在线路由,数据伸缩等场景。

(4)redis cluster缺点

    1)key批量操作支持有限

    2)key事务的操作支持有限,同理只支持key在同一节点上的事务操作

    3)key作为数据分区的最小粒度,因此不能将一个大的键值对象如hash、list等映射到不同的节点

    4)不支持多数据库空间,集群模式下只能使用一个数据库空间。

    5)复制结构只支持一层,不支持嵌套树状复制结构。

2、集群的搭建

(1)准备节点

    Redis cluster节点数量至少为6个才能保证完成高可用性集群,每个节点需要配置”cluster-enabled yes”。由于在每台机器上起了两个redis节点,需要为每个节点统一规划目录,节点的准备如下:

角色

IP地址

端口

内存大小

备注

Redis master

192.168.16.128

6379

16g

主节点

Redis master

192.168.16.129

6379

16g

主节点

Redis master

192.168.16.130

6379

16g

主节点

Redis slave

192.168.16.128

6380

16g

16.129从节点

Redis slaver

192.168.16.129

6380

16g

16.130从节点

Redis slaver

192.168.16.130

6380

16g

16.128从节点

(2)节点的配置启动

    Redis cluster相关的主要配置如下(各个节点根据节点的具体需求进行配置):

# 端口
port 6379
# 开启集群模式
cluster-enabled yes
# 集群的内部配置文件
cluster-config-file nodes-6379.conf
# 节点的超时时间,单位毫秒
cluster-node-timeout 15000
# 数据存放目录,不存在时需要创建,不然不能启动
dir "/var/lib/redis/6379"
# 日志存放文件
logfile "/var/log/redis/redis_6379.log"
# 运行时产生的pid文件存放目录
pidfile "/var/run/redis_6380.pid"

    redis配置完成后,需要启动所有的节点,由于是一个机器上部署了两个redis实例,占用了不同的端口;启动时通过命令”redis-server /etc/redis/6379/6379.conf”来启动

# 启动192.168.16.128上的两个redis
]# redis-server /etc/redis/6380/6380.conf
]# redis-server /etc/redis/6379/6379.conf
# 查看端口有没有被监听
]# ss -tanl | egrep "6379|6380"
LISTEN     0      128                       *:16379                    *:*     
LISTEN     0      128                       *:16380                    *:*     
LISTEN     0      128                       *:6379                     *:*     
LISTEN     0      128                       *:6380                     *:*  

    Redis cluster启动成功后,如果没有cluster的配置文件则会自动生成一份集群的配置文件,存放在redis数据目录下,当集群内节点信息发生变化时,节点会自动保存集群状态到配置文件中。节点集群配置文件中最最要的为节点的ID,当各个节点启动成功后,每个节点彼此不知道其他节点的存在,需要通过”握手”让6个节点建立联系组成一个集群。

(3)节点的握手

    节点握手是指一批运行在集群模式下的节点通过Gossip协议彼此通信,达到感知对方的过程。节点握手时集群彼此通信的第一步,只需要在集群内的任意节点上执行”cluster meet {ip} {port}”命令加入新节点,握手消息会通过消息在集群内传播,这样其他节点会自动发现新节点并发起握手流程。

# 执行meet命令让所有的节点互相握手
127.0.0.1:6379> cluster meet 192.168.16.128 6379
OK
127.0.0.1:6379> cluster meet 192.168.16.128 6380
OK
127.0.0.1:6379> cluster meet 192.168.16.129 6379
OK
127.0.0.1:6379> cluster meet 192.168.16.129 6380
OK
127.0.0.1:6379> cluster meet 192.168.16.130 6379
OK
127.0.0.1:6379> cluster meet 192.168.16.130 6380
OK
# 查看集群的状态
127.0.0.1:6379> cluster nodes
d33ca65e915d9c0b2a84c288b3a492df0705fa24 192.168.16.130:6380 master - 0 1535907782856 5 connected
faeed9b174f5506ca205cd5864806f0716c969c2 192.168.16.129:6379 master - 0 1535907781336 0 connected
99a04a3a54fea878ca0bda40c0053e7f612a4941 192.168.16.129:6380 master - 0 1535907783362 3 connected
ad864130ea5472462b3406563fdf14386465f7da 192.168.16.128:6379 myself,master - 0 0 2 connected
174d5e01ff5fdaa5d10646483780afb34dd6b12b 192.168.16.130:6379 master - 0 1535907784374 4 connected
6a38614369457a50da47a6572d22e8c0befb004d 192.168.16.128:6380 master - 0 1535907782346 1 connected

    节点握手后集群还不能正常工作,只有将槽分配到对应的节点后集群才能正常工作。

(4)分配槽

    节点握手完成后,需要为节点分配槽,redis 集群把所有的数据映射到16384个槽中,刻个key会映射一个固定的槽,只有当节点分配了槽,才能相应和槽关联的命令,为节点分配槽时通过”cluster addslots”命令完成的。

# 为各主节点分配槽
]# redis-cli -h 192.168.16.128 -p 6379 cluster addslots {0..5461}
OK
]# redis-cli -h 192.168.16.129 -p 6379 cluster addslots {5462..10992}
OK
]# redis-cli -h 192.168.16.130 -p 6379 cluster addslots {10993..16282}
OK
# 分配完槽在查看节点状态时,各节点获取了相应的槽,集群进入在线状态
cluster nodes
d33ca65e915d9c0b2a84c288b3a492df0705fa24 192.168.16.133:6380 master - 0 1535908778762 5 connected
faeed9b174f5506ca205cd5864806f0716c969c2 192.168.16.129:6379 master - 0 1535908779266 0 connected 5462-10992
99a04a3a54fea878ca0bda40c0053e7f612a4941 192.168.16.129:6380 master - 0 1535908777752 3 connected
ad864130ea5472462b3406563fdf14386465f7da 192.168.16.128:6379 myself,master - 0 0 2 connected 0-5461
174d5e01ff5fdaa5d10646483780afb34dd6b12b 192.168.16.133:6379 master - 0 1535908776737 4 connected 10993-16282
6a38614369457a50da47a6572d22e8c0befb004d 192.168.16.128:6380 master - 0 1535908779774 1 connected

    再为主节点分配完槽后,还需要使用”cluster replicate {nodeId}”命令为每一个主节点分配一个从节点,该命令必须要在对应的从节点上执行,{nodId}为要复制的主节点的id。

# 让192.168.16.128:6380成为192.168.16.129:6279的从节点
192.168.16.128:6380> cluster replicate faeed9b174f5506ca205cd5864806f0716c969c2
OK
# 让192.168.16.129:6380成为192.168.16.130:6279的从节点
192.168.16.129:6380> cluster replicate 174d5e01ff5fdaa5d10646483780afb34dd6b12b
OK
# 让192.168.16.130:6380成为192.168.16.128:6279的从节点
192.168.16.130:6380> cluster replicate ad864130ea5472462b3406563fdf14386465f7da
OK
# 再次查看节点状态时各主节点都有了从节点
127.0.0.1:6380> cluster nodes
6a38614369457a50da47a6572d22e8c0befb004d 192.168.16.128:6380 myself,slave faeed9b174f5506ca205cd5864806f0716c969c2 0 0 1 connected
faeed9b174f5506ca205cd5864806f0716c969c2 192.168.16.129:6379 master - 0 1535909496378 0 connected 5462-10992
99a04a3a54fea878ca0bda40c0053e7f612a4941 192.168.16.129:6380 slave 174d5e01ff5fdaa5d10646483780afb34dd6b12b 0 1535909495367 4 connected
174d5e01ff5fdaa5d10646483780afb34dd6b12b 192.168.16.133:6379 master - 0 1535909494358 4 connected 10993-16282
d33ca65e915d9c0b2a84c288b3a492df0705fa24 192.168.16.133:6380 slave ad864130ea5472462b3406563fdf14386465f7da 0 1535909493348 5 connected
ad864130ea5472462b3406563fdf14386465f7da 192.168.16.128:6379 master - 0 1535909491828 2 connected 0-5461

3、使用redis-trib.rb快速搭建集群

    当集群内的节点数量多时,通过手动的方式搭建集群费时费力,此时可通过redis-trib.rb来快速的搭建集群。

    Redis-trib.rb是采用ruby实现的redis集群管理工具,内部通过Cluster相关命令帮助我们简化集群创建、检查、槽迁移和均衡等常见的操作;使用redis-trib.rb之前需要安装ruby依赖环境。

(1)安装前准备

    使用redis-trib.rb搭建集群时由于机器有限将使用一台新的机器,启动6个redis实例完成集群的搭建,各redis实例的安装配置启动同上面一样。

角色

IP地址

端口

备注

Redis master

192.168.16.134

6379

各主从节点是随机分配的,在生产中建议使用多台机器,主从节点不会分配在同一台机器上

Redis master

192.168.16.134

6380

Redis master

192.168.16.134

6381

Redis slave

192.168.16.134

6382

Redis slaver

192.168.16.134

6383

Redis slaver

192.168.16.134

6384

(2)安装ruby及相关依赖

1)安装ruby

# 下载安装
# 安装redis所需要的依赖
]# yum install zlib zlib-devel 
]# wget http://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.1.tar.gz
]# tar -xf ruby-2.5.1.tar.gz 
]# cd ruby-2.5.1
]# ./configure --prefix=/usr/local/ruby
]# make && make install
# 建立快捷方式加入系统环境变量中或直接加环境变量
]# ln -s /usr/local/ruby/bin/ruby /usr/local/bin/
]# ln -s /usr/local/ruby/bin/gem /usr/local/bin/
         2)安装redis-trib.rb

# 安装redis插件,这一步安装时有时会报错,这次顺利安装
]# gem install redis
# 将redis源码包下的” redis-trib.rb”拷贝到系统环境变量下
]# cp /usr/local/src/redis-3.2.12/src/redis-trib.rb /usr/local/bin/redis-trib.rb

    3)使用”redis-trib.rb”快速创建集群

# 使用”redis-trib.rb快速创建集群”
]# redis-trib.rb create --replicas 1 192.168.16.134:6379 192.168.16.134:6380 192.168.16.134:6381 192.168.16.134:6382 192.168.16.134:6383 192.168.16.134:6384

    4)查看集群的状态信息

    检查集群的状态或查看集群的信息通过任意一台节点均可操作。操作命令分别如下:

        检查集群的状态:redis-trib.rb check <nodeip>:<nodeport>

        查看集群的信息:redis-trib.rb info <nodeip>:<nodeport>

# 检查集群的状态
]# redis-trib.rb check 192.168.16.134:6379
>>> Performing Cluster Check (using node 192.168.16.134:6379)
M: 2411c6c80e9f9473ab8971eccf39a6f1e7ef3024 192.168.16.134:6379
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
S: 10aff3883025046ceba675d4272c7bdfd524a0c4 192.168.16.134:6384
   slots: (0 slots) slave
   replicates 333995e83ce190a5e6c52f8a7c216a9b73ef76ad
S: 3695a2eb1f7c10dcee7a3a61eccab57a296298c5 192.168.16.134:6382
   slots: (0 slots) slave
   replicates 2411c6c80e9f9473ab8971eccf39a6f1e7ef3024
S: a906637c42295a1f29b2eef1273a8a6c27f545d1 192.168.16.134:6383
   slots: (0 slots) slave
   replicates 8b3f2a2b393d593e4d33057223545a4308762858
M: 333995e83ce190a5e6c52f8a7c216a9b73ef76ad 192.168.16.134:6381
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
M: 8b3f2a2b393d593e4d33057223545a4308762858 192.168.16.134:6380
   slots:5461-10922 (5462 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.

4redis cluster节点通信

    Redis cluster各节点启动后,会发现本地除了监听配置文件中的端口外,还会监听另一个redis节点监听的端口加”10000”的端口,此端口主要用于各节点之间的通信。Redis各节点之间通信采用的是p2p的Gossip(流言)协议,Gossip协议工作的原理就是节点彼此不断通信交换信息,一段时间后所有节点都会知道集群的信息。

(1)Gossip消息的类型

    1)ping消息:用于检测节点是否在线和交换彼此状态信息

    2)meet消息:用于通知新节点的加入

    3)pong消息:当接收到ping、meet消息时,作为响应消息回复给发送方的确认消息

    4)fail消息:当节点判定集群内一个节点下线时,会向集群内广播一个fail消息,其他节点接收到fail消息时把对应的节点更新为下线状态。

(2)通信节点的选择

    集群内每个节点维护定时任务默认每秒执行10次,每次会随机选取5个节点找出最久没有通信的节点发送ping消息,用于保证Gossip信息交换的随机性。

二、redis集群的管理

1、扩容集群

    Redis集群的扩容可以通过”准备节点”——>”让节点加入集群”——>”迁移槽和数据到新增节点”的流程完成集群的扩容;迁移槽和数据到新节点过程手动操作时由于过程较多,容易出错,这个过程可以通过”redis-trib”提供的槽重分片功能快速的完成槽的重新分片。

以下的操作均基于通过”redis-trib-rb”快速搭建的单机多实例的集群中操作。

(1)准备新节点

角色

IP地址

端口

Redis master

192.168.16.134

6385

Redis master

192.168.16.134

6386

(2)让节点加入集群

# 让新节点加入到集群中
127.0.0.1:6379> CLUSTER MEET 192.168.16.134 6385
127.0.0.1:6379> CLUSTER MEET 192.168.16.134 6386
# 查看新添加节点状态时由于没有分配槽,还不能正常工作
127.0.0.1:6379> cluster nodes
9e2e045b752b467313d4b21ecc42b8d9a4c1a3dc 192.168.16.134:6386 master - 0 1536001730850 0 connected
0bde7ccda11f686ffe3b5a2ad4020c282710018f 192.168.16.134:6385 master - 0 1536001727822 7 connected
……

    除了使用”cluster meet”命令让节点加入集群,还可以使用”redis-trib.rb”工具让新增节点加入集群,如果使用”redis-trib.rb”让节点加入集群,则执行的命令为(在生产环境中建议使用”redis-trib.rb”命令加入新节点):

redis-trib.rb add-node 192.168.16.134:6385 192.168.16.134:6379
redis-trib.rb add-node 192.168.16.134:6385 192.168.16.134:6379

(3)手动迁移槽和数据

    在手动迁移槽和数据前需要为新节点指定槽迁移计划,确定原有槽的那些数据需要迁移到新节点;迁移计划中要保证每个节点负责相似数量的槽,从而保证各节点数据的均匀。

    迁移的流程如下:

     1)对目标节点发送”cluster setslot {slot} importing {sourceNodeId}”命令,让目标节点准备导入槽数据

    2)对源节点发送”cluster setslot {slot} migrating {targetNodeId}”命令,让源节点准备迁出槽的数据。

    3)源节点循环执行”cluster getkeysinslot {slot} {count}”命令,获取count个属于{slot}的键

    4)在源节点上执行”migrate {targetIp} {gargetPort} “” 0 {timeout} keys {key…}”命令,把获取到的键通过流水线(pipeline)机制批量迁移到目标节点;重复执行步骤3和4知道槽写所有的键值数据都迁移到目标节点

    5)向集群内的所有节点发送”cluster setslot {slot} node {targetNodeId}”命令,通知槽分配给目标节点。

(4)使用槽重分片功能”redis-trib”

    命令:redis-trib.rb reshard host:port –from <arg> --to <arg> --slots <arg> --yes –timeout <arg> --pipline <arg>

    参数:

       Host:port:集群内任意几点地址

       --from:指定源节点的Id,如果有多个源节点,使用逗号分隔

       --to:需要迁移的目标节点的id

       --slots:需要迁移槽的总数量,在迁移过程中提示用户输入,

       --yes:当打印出reshard执行计划时,是否需要用户输入yes确认后在执行reshard

       --timeout:控制每次migrate操作的超时时间,默认为60000毫秒

       --pipeline:控制每次迁移键的数量,默认为10

# 使用redis-trib.rb完成数据的迁移和槽的重新分片
]# redis-trib.rb reshard 127.0.0.1:6379

    在迁移的过程中要求输入迁移的槽的数量,目标节点的id(只能输入一个),源节点的id(根据自己的集群环境输入,输出完成后输入”done”回车完成输入)

# 迁移完成后查看新节点槽状态,已经分配了槽,槽不连续不影响redis集群的使用
127.0.0.1:6379> CLUSTER NODES
……
0bde7ccda11f686ffe3b5a2ad4020c282710018f 127.0.0.1:6385 master - 0 1536004597778 7 connected 0-1364 5461-6826 10923-12287

(5)为新添加的主节点添加从节点

# 为新增主节点添加从节点
192.168.16.134:6386> CLUSTER REPLICATE 0bde7ccda11f686ffe3b5a2ad4020c282710018f
# 查看节点状态时从节点已经开始复制主节点
192.168.16.134:6386> cluster nodes
……
9e2e045b752b467313d4b21ecc42b8d9a4c1a3dc 127.0.0.1:6386 myself,slave 0bde7ccda11f686ffe3b5a2ad4020c282710018f 0 0 0 connected

2、收缩集群

    Redis集群能够扩容,也就能够收缩,收缩redis集群的流程与扩容redis集群的流程恰恰相反。

(1)迁移下线节点负责的槽及数据

    在使用” redis-trib.rb reshard”命令迁移槽及数据到目标节点时,由于目标节点只能输入一个,当有多个节点时需要执行多次” redis-trib.rb reshard”命令将要下线的节点的槽及数据迁移到其他节点。

    下线计划:下线节点192.168.16.134:6379,将此节点负责的槽及数据迁移到其他的三个节点上。

# 查看节点192.168.16.134:6379负责的槽
127.0.0.1:6379> CLUSTER NODES
2411c6c80e9f9473ab8971eccf39a6f1e7ef3024 192.168.16.134:6379 myself,master - 0 0 1 connected 1365-5460
# 迁移4095个槽到192.168.16.124:6380
]# redis-trib.rb reshard 192.168.16.134:6379
……
# 输入迁移槽数量
How many slots do you want to move (from 1 to 16384)? 1365  
# 迁移到的目标节点192.168.16.134:6380的id
What is the receiving node ID? 8b3f2a2b393d593e4d33057223545a4308762858
Please enter 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.
# 迁移到的源节点192.168.16.134:6379的id,输入完成后输入done结束
Source node #1:2411c6c80e9f9473ab8971eccf39a6f1e7ef3024
Source node #2:done
……

    迁移完成后,按照上面的迁移方法,分别迁移1366、1365个槽到节点192.168.16.134:6381及节点192.168.16.134:6382。

# 迁移后的个主节点的槽分布如下
127.0.0.1:6379> CLUSTER NODES
333995e83ce190a5e6c52f8a7c216a9b73ef76ad 192.168.16.134:6381 master - 0 1536006341658 9 connected 2730-4095 12288-16383
2411c6c80e9f9473ab8971eccf39a6f1e7ef3024 192.168.16.134:6379 myself,master - 0 0 1 connected
8b3f2a2b393d593e4d33057223545a4308762858 192.168.16.134:6380 master - 0 1536006345714 8 connected 1365-2729 6827-10922
0bde7ccda11f686ffe3b5a2ad4020c282710018f 127.0.0.1:6385 master - 0 1536006343700 10 connected 0-1364 4096-6826 10923-12287

(2)忘记节点

    槽迁移完成后,为了让其他节点不再与下线节点进行Gossip消息交换,需要让集群内的所有节点忘记要下线的几点。

    命令:redis-trib.rb del-node {host:port} {downNodeId}

# 让所有几点忘记下线的节点192.168.16.134:6379及它的从节点192.168.16.134:6379:6382
]# redis-trib.rb del-node 192.168.16.134:6379 2411c6c80e9f9473ab8971eccf39a6f1e7ef3024
>>> Removing node 2411c6c80e9f9473ab8971eccf39a6f1e7ef3024 from cluster 192.168.16.134:6379
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.
]# redis-trib.rb del-node 192.168.16.134:6382 3695a2eb1f7c10dcee7a3a61eccab57a296298c5

    忘记节点后再次查看节点状态时,集群中已经没有下线节点192.168.16.134:6379及节点192.168.16.134:6382的信息。

192.168.16.134:6380> CLUSTER NODES
0bde7ccda11f686ffe3b5a2ad4020c282710018f 192.168.16.134:6385 master - 0 1536006923917 10 connected 0-1364 4096-6826 10923-12287
a906637c42295a1f29b2eef1273a8a6c27f545d1 192.168.16.134:6383 slave 8b3f2a2b393d593e4d33057223545a4308762858 0 1536006921379 8 connected
8b3f2a2b393d593e4d33057223545a4308762858 192.168.16.134:6380 myself,master - 0 0 8 connected 1365-2729 6827-10922
333995e83ce190a5e6c52f8a7c216a9b73ef76ad 192.168.16.134:6381 master - 0 1536006926953 9 connected 2730-4095 12288-16383
10aff3883025046ceba675d4272c7bdfd524a0c4 192.168.16.134:6384 slave 333995e83ce190a5e6c52f8a7c216a9b73ef76ad 0 1536006924931 9 connected
9e2e045b752b467313d4b21ecc42b8d9a4c1a3dc 127.0.0.1:6386 slave 0bde7ccda11f686ffe3b5a2ad4020c282710018f 0 1536006925939 10 connected

3、连接集群

(1)连接重定向

    Redis在集群模式下接受任何键相关命令时首先计算键对应的槽,再根据槽找出所对应的节点,如果节点时自身则处理请求命令,否则恢复move重定向错误,通知客户端请求正确的节点。如果在使用”redis-cli”命令时加”-c”参数则会自动重定向。

(2)程序连接redis

    smart客户端支持集群协议。

三、redis集群故障的发现与恢复

1、故障的发现

(1)主观下线(pfail)

    某个节点认为一个节点不可用

(2)客观下线(fail)

    集群内多个节点都认为某个节点不可用,从而达成共识标识该节点下线;如果该节点为主节点则要进行故障转移

2、故障恢复

    故障节点变为客观下线后,如果下线节点时持有槽的主节点,则需要在它的从节点中选举出一个替换它。选举流程如下

(1)资格检查

(2)准备选举时间

(3)发起选举

(4)选举投票

(5)替换主节点

3、手动故障转移

    Redis支持手动故障转移功能,指定从节点发起故障转移流程,主从节点进行故障的切换。

   手动故障转移命令:cluster failover

 

猜你喜欢

转载自blog.csdn.net/dayi_123/article/details/82622339