06-redis的cluster集群

发布时间 2023-12-26 20:06:08作者: EJW

一、介绍

Redis 集群是一个可以在多个 Redis 节点之间进行数据共享的设施(installation)。
Redis 集群不支持那些需要同时处理多个键的 Redis 命令, 因为执行这些命令需要在多个 Redis 节点之间移动数据, 并且在高负载的情况下, 这些命令将降低 Redis 集群的性能, 并导致不可预测的行为。
Redis 集群通过分区(partition)来提供一定程度的可用性(availability): 即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求。
将数据自动切分(split)到多个节点的能力。
当集群中的一部分节点失效或者无法进行通讯时, 仍然可以继续处理命令请求的能力。

二、实现原理

集群使用公式 CRC16(key) & 16383 计算键 key属于哪个槽
image

Redis 集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现: 一个 Redis 集群包含 16384 个哈希槽(hash slot), 数据库中的每个键都属于这 16384 个哈希槽的其中一个, 集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽, 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。

image

三、运行机制

所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.
节点的fail是通过集群中超过半数的master节点检测失效时才生效.
客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->key

四、主从复制机制

为了使得集群在一部分节点下线或者无法与集群的大多数(majority)节点进行通讯的情况下, 仍然可以正常运作, 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 集群还是会停止运作。

集群的复制特性重用了 SLAVEOF 命令的代码,所以集群节点的复制行为和 SLAVEOF 命令的复制行为完全相同。

五、集群的故障转移

在集群里面,节点会对其他节点进行下线检测。

当一个主节点下线时,集群里面的其他主节点负责对下线主节点进行故障转移。

换句话说,集群的节点集成了下线检测和故障转移等类似 Sentinel 的功能。

因为 Sentinel 是一个独立运行的监控程序,而集群的下线检测和故障转移等功能是集成在节点里面的,它们的运行模式非常地不同,所以尽管这两者的功能很相似,但集群的实现没有重用 Sentinel 的代码。

六、在集群里面执行命令的两种情况

第一种:命令发送到了正确的节点:命令要处理的键所在的槽正好是由接收命令的节点负责,那么该节点执行命令,就像单机 Redis 服务器一样。

第二种:命令发送到了错误的节点:接收到命令的节点并非处理键所在槽的节点,那么节点将向客户端返回一个转向(redirection)错误,告知客户端应该到哪个节点去执行这个命令,客户端会根据错误提示的信息,重新向正确的节点发送命令

命令发送给正确的节点

键 date 位于 2022 槽,该槽由节点 7000 负责,命令会直接执行。
image

命令发送给了错误的节点

image

七、如何实现转向功能

集群中的节点会互相告知对方,自己负责处理哪些槽。

image

  • 集群中的每个节点都会记录 16384 个槽分别由哪个节点负责,从而形成一个“槽表”(slot table)。
    节点在接收到命令请求时,会通过槽表检查键所在的槽是否由本节点处理:
    • 如果是的话,那么节点直接执行命令;
    • 如果不是的话,那么节点就从槽表里面提取出正确节点的地址信息,然后返回转向错误。

八、redis cluster 搭建

8.1 规划

6个redis实例,端口号:7000-7005 一般会放到3台硬件服务器

注:在企业规划中,一个分片的两个节点,分到不同的物理机,防止硬件主机宕机造成的整个分片数据丢失。

8.2 Redis Cluster配置插件安装

# EPEL源安装ruby支持
yum install ruby rubygems -y
# 使用国内源
gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/
gem install redis -v 3.3.3
gem sources -l

# 如果无法使用,可以使用aliyun
gem sources -a http://mirrors.aliyun.com/rubygems/ 
gem sources  --remove http://rubygems.org/

8.3 添加cluster 配置文件

创建六个redis 数据目录,mkdir /data/700{0..5}
然后修改不同的端口号码,和数据路径

vim /data/7000/redis.conf
port 7000
daemonize yes
pidfile /data/7000/redis.pid
loglevel notice
logfile "/data/7000/redis.log"
dbfilename dump.rdb
dir /data/7000
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
配置文件说明
port 7000
# bind 127.0.0.1
# 修改保护模式关闭
protected-mode no
# 以守护线程启用
daemonize yes
# 启用集群
cluster-enabled yes 
# 配置每个节点的配置文件,同样以端口号为名称
cluster-config-file nodes-7000.conf
# 配置集群节点的超时时间,可不改,默认也是
cluster-node-timeout 15000  
# 启动AOF增量持久化策略
appendonly yes  
# 发生改变就记录日志
appendfsync always 

说明:Redis 集群由多个运行在集群模式(cluster mode)下的 Redis 实例组成, 实例的集群模式需要通过配置来开启, 开启集群模式的实例将可以使用集群特有的功能和命令

8.4 启动所有节点

redis-server /data/7000/redis.conf 
redis-server /data/7001/redis.conf 
redis-server /data/7002/redis.conf 
redis-server /data/7003/redis.conf 
redis-server /data/7004/redis.conf 
redis-server /data/7005/redis.conf 

[root@db01 ~]# ps -ef |grep redis
root       8854      1  0 03:56 ?        00:00:00 redis-server *:7000 [cluster]     
root       8858      1  0 03:56 ?        00:00:00 redis-server *:7001 [cluster]     
root       8860      1  0 03:56 ?        00:00:00 redis-server *:7002 [cluster]     
root       8864      1  0 03:56 ?        00:00:00 redis-server *:7003 [cluster]     
root       8866      1  0 03:56 ?        00:00:00 redis-server *:7004 [cluster]     
root       8874      1  0 03:56 ?        00:00:00 redis-server *:7005 [cluster]  

8.5 将节点加入集群管理

redis-trib.rb create --replicas 1 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

说明:选项 --replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。前边三个节点会设置成主节点,对应的会设置成主节点的从节点

8.6 集群状态查看

//集群主节点状态
redis-cli -p 7000 cluster nodes | grep master
//集群从节点状态
redis-cli -p 7000 cluster nodes | grep slave

九、集群管理

9.1 添加节点

1、 创建两个新的实例并启动,然后添加节点到集群

// 添加127.0.0.1:7006 到127.0.0.1:7000(一台现有集群的主库)管理的集群
redis-trib.rb add-node 127.0.0.1:7006  127.0.0.1:7000

2、 转移slot(重新分片)

redis-trib.rb reshard 127.0.0.1:7000
image

3、添加从节点

// 向所在7000的集群添加127.0.0.1:7007节点且成为master-id是...afdd3cd622a267b的从库
redis-trib.rb add-node --slave --master-id 13325c2099422016da3daff51afdd3cd622a267b  127.0.0.1:7007 127.0.0.1:7000

9.2 删除节点

删除master节点之前首先要使用reshard移除master的全部slot,然后再删除当前节点

1、将需要删除节点slot移动走(接收槽位的节点只能有一个,比较坑)

redis-trib.rb reshard 127.0.0.1:7000

image

2、删除一个节点

// 主节点删除:
redis-trib.rb del-node 127.0.0.1:7006 13325c2099422016da3daff51afdd3cd622a267b

// 从节点删除:
redis-trib.rb del-node 127.0.0.1:7007 7f20e56d1860ee0009818b7f04ecc460873c429a