Docker 下Redis Cluster 分片集群搭建
1. Cluster 分片集群
1.1 Cluster 集群的结构和作用
redis 哨兵模式虽然提供了 redis⾼可⽤、高并发读的解决方案,但是在海量数据应用场景下,仍然存在海量数据存储问题和高并发写的问题。当只有⼀个 Master 对外提供服务时,如果数据量特别⼤,内存占⽤问题严重,数据的高并发写、数据备份和恢复都会⼤⼤降低效率。
针对这些问题,redis 推出 Cluster 集群架构,该结构具有如下特点:
- Redis Cluster 采用的是基于 P2P 的去中心化的网络拓扑架构,没有中心节点,所有节点既是数据存储节点,也是控制节点;
- 引入槽(slot)的概念,通过 CRC+hashslot 算法支持多个主节点(分片),每个主节点分别负责存储一部分数据,这样理论上可以支持无限主节点的水平扩容以便支持海量吞吐量;
- 内置类似哨兵的高可用机制,能够实现自动故障转移,保证每个主节点的高可用。
因此,redis Cluster 集群也叫分片集群,具有分片存储的特性,不需要哨兵也可以完成故障转移的功能,具有⾼可⽤性,性能优于哨兵模式,可实现⾃动扩容(官⽅建议不要超过 1000 个节点)。
1.2 Cluster 分片集群 的作用
Cluster 分片集群的作用如下:
- 集群中有多个 master,每个 master 保存不同数据;
- 每个 master 都可以有多个 slave 节点;
- master 之间通过 ping 监测彼此健康状态;
- 客户端请求可以访问集群任意节点,最终都会被转发到正确节点。
1.3哈希槽(hash slot)
1.3.1 插槽原理
在 Cluster 集群里设置了 16384 个哈希槽(hash slot),每个 redis 节点负责管
理一部分槽的读写操作。Redis 会把每一个 master 节点映射到 0~16383 共 16384 个插槽
(hash slot)上。当在 master 节点上写键值对数据时,redis 先对每个键(key),用
CRC16 算法对 key 进行运算,然后用 16384 对运算结果取模,余数作为插槽,寻找插槽
所在实例即可,就把这个 key 放入相应编号的哈希槽中。
下图为 Redis 的分片集群进行数据分片存储示意图。
此外,cluster 集群也支持主从复制模式,每个主节点可以携带一个或多个从节点,如下图所示。
2. Cluster 分片集群的搭建
2.1 场景描述
(1)配置六个 redis 服务器,形成一主一从,共 3 组的分片集群,具体如下图所
示:
(2)注意:因Redis-5.0.0 以后的版本才开始支持分片集群的创建,所以 Windows下的 Redis 不能直接使用 redis-cli 来建立集群,需要安装另外的工具才可以创建,具体可参考以下链接:
http://www.yayihouse.com/yayishuwu/chapter/2417
所以,以下直接使用 Docker 进行 Redis 的分片集群搭建。
2.2实验步骤(Linux环境完成)
六个 Redis 服务节点的 IP 和配置文件如下:
主节点 1: IP:127.0.0.1 6379,配置文件:redis-6379.conf
主节点 2: IP:127.0.0.1 6380,配置文件:redis-6380.conf
主节点 3: IP:127.0.0.1 6381,配置文件:redis-6381.conf
从节点 4: IP:127.0.0.1 26379,配置文件:redis-26379.conf
从节点 5 :IP:127.0.0.1 26380,配置文件:redis-26380.conf
从节点 6 :IP:127.0.0.1 26381,配置文件:redis-26381.conf
在宿主机中创建conf_cluster文件夹
比如我的文件夹路径为/mydata/conf_cluster(运行容器时挂载目录会用到):
conf_cluster文件夹结构
conf_cluster中文件内容:
redis-6379.conf:
port 6379
#开启分片集群
cluster-enabled yes
#指定分片集群需要使用的节点配置文件名
cluster-config-file nodes-6379.conf
redis-6380.conf
port 6380
cluster-enabled yes
cluster-config-file nodes-6380.conf
redis-6381.conf
port 6381
cluster-enabled yes
cluster-config-file nodes-6381.conf
redis-6382.conf
port 6382
cluster-enabled yes
cluster-config-file nodes-6382.conf
redis-26379.conf
port 26379
cluster-enabled yes
cluster-config-file nodes-26379.conf
redis-26380.conf
port 26380
cluster-enabled yes
cluster-config-file nodes-26380.conf
redis-26381.conf
port 26381
cluster-enabled yes
cluster-config-file nodes-26381.conf
配置文件中配置命令解释
- 开启分片集群
命令:cluster-enabled yes
- 指定分片集群需要使用的节点配置文件名
命令:cluster-config-file 配置文件名
如 :cluster-config-file nodes-6379.conf , 该文件会由 Redis 自动创建 , 此处只需要给出配置文件名(“配置文件名”处只用给个文件名,不用自己创建)
启动 docker 服务,并创建 6 个 Redis 容器
注意这里docker run命令中主机对应的路径要按照自己的实际路径对命令进行修改。例如我的宿主机中conf_cluster文件夹路径为/mydata/conf_cluster
(1)节点6379
docker run -id --name redis_6379 -p 6379:6379 --privileged=true -v /mydata/conf_cluster/data/6379:/data -v/mydata/conf_cluster/redis-6379.conf:/etc/redis/redis-6379.conf redis redis-server /etc/redis/redis-6379.conf
(2)节点6380
docker run -id --name redis_6380 -p 6380:6380 --privileged=true -v /mydata/conf_cluster/data/6380:/data -v/mydata/conf_cluster/redis-6380.conf:/etc/redis/redis-6380.conf redis redis-server /etc/redis/redis-6380.conf
(3)节点6381
docker run -id --name redis_6381 -p 6381:6381 --privileged=true -v /mydata/conf_cluster/data/6381:/data -v/mydata/conf_cluster:/etc/redis/ redis redis-server /etc/redis/redis-6381.conf
(4)节点26379
docker run -id --name redis_26379 -p 26379:26379 --privileged=true -v/mydata/conf_cluster/redis-26379.conf:/etc/redis/redis-26379.conf redis redis-server /etc/redis/redis-26379.conf
(5)节点26380
docker run -id --name redis_26380 -p 26380:26380 --privileged=true -v/mydata/conf_cluster/redis-26380.conf:/etc/redis/redis-26380.conf redis redis-server /etc/redis/redis-26380.conf
(6)节点26381
docker run -id --name redis_26381 -p 26381:26381 --privileged=true -v/mydata/conf_cluster/redis-26381.conf:/etc/redis/redis-26381.conf redis redis-server /etc/redis/redis-26381.conf
查看6台服务器启动情况
命令:docker ps -a
(查看所有(没有在运行的也会查到))或 docker ps
(查看在运行的)
可以看出,redis 节点容器成功创建并启动了
查询每个 redis 节点的容器内 IP
命令:docker inspect 容器名或容器ID
(查询一个容器的信息)
如查询 6379 节点容器信息:docker inspect redis_6379
可以看到我这里redis_6379在容器内ip为172.17.0.5(注意电脑上的docker中容器内ip可能不同的):
同理查出各个节点的ip,用于后续的配置
创建集群:将 6 个节点创建成 3 主 主 3 从的分片集群
以上操作,只是配置了 6 个 Redis 节点,还没有构成分片集群。Redis Cluster 在 5.0之后取消了 ruby 脚本 redis-tri.rb 的支持,将该功能集成到了 redis-cli 命令里,因此创建集群时,可直接使用 redis-cli --cluster
命令来创建。
命令:redis-cli --cluster help
可查询集群创建相关参数
命令:redis-cli --cluster create --cluster-replicas 1 <节点1> ,< 节点2>...
参数说明:
–cluster create:表示要创建集群
–cluster-replicas 1:表示一个主节点配置一个从节点
如,根据以上查询的各节点的容器内 IP,可以使用以下命令创建分片集群。
其中,redis 会根据–cluster-replicas 1 参数,自动平均分配 6 个节点,前 3 个为主节点,后 3 个
为从节点:
(注意这里的ip要根据实际查出来的ip进行修改)
redis-cli --cluster create 172.17.0.3:6379 172.17.0.5:6380 172.17.0.6:6381 172.17.0.7:26379 172.17.0.8:26380 172.17.0.9:26381 --cluster-replicas 1
进入任意一个 docker 容器内,执行以上命令:
同意该分配方案,则会进行如下配置信息:
最后,集群搭建成功。
连接任一节点, 查看分配集群结构的信息
在分片集群中,通过任一节点都可进入集群,进行操作。
命令:cluster info
显示集群的相关信息。
如,以下进入节点 6380 容器内,查询集群信息,可以看到集群状态正常
查看集群节点的信息
命令:cluster nodes
查看各节点信息,如主从信息,节点 ID 等。
Redis分片集群操作和故障处理
1. 操作分片集群
在分片集群中,通过任一节点都可进入集群,进行操作。以下以 6381 节点为例。
(1)进入 6381 节点容器内:
命令:docker exec -it redis_6381 /bin/bash
(2)连接到 redis 上, ,如 6381 节点:
命令:redis-cli -c -p 6381
参数说明: -c 表示进入集群环境,一定要加上该参数。
(3)插入一个键值对数据
插入键值对时,集群会计算键的 slot 值,并存储到相应的 redis 节点上,如下图所示。
(4)查询数据
查询数据时,同样会计算键的 slot 值,并到相应的 redis 节点上取出数据,见下图;
实际操作实验:
所以,在 redis 分片集群中,数据是跟 slot 绑定的,而不是跟 redis 节点绑定,访问集群中的任意一个节点,都可以查询到数据。
2 扩容:在已有集群中添加新节点
2.1 使用命令
命令:redis-cli --cluster add-node 新节点IP 旧节点IP
参数说明:
add-node :添加节点,把新节点加入到指定的集群,默认添加的主节点
如果添加的从节点,则需要以下两个参数:
–cluster-slave : 新节点作为从节点
–cluster-master-id 旧节点:给新节点指定主节点
2.2 扩容实验
(1 )扩容需求:
- 向集群中添加一个新的 master 主节点,端口号为 6382 ,配置文件见redis_6382.conf 文件;
- 向 6382 节点分配 slot 插槽。
(2)执行以下命令,创建 redis_6382 节点的容器
docker run -id --name redis_6382 -p 6382:6382 --privileged=true -v /mydata/conf_cluster/data/6382:/data -v/mydata/conf_cluster/redis-6382.conf:/etc/redis/redis-6382.conf redis redis-server /etc/redis/redis-6382.conf
(3)查询 redis_6382 节点的容器内 IP
命令:
docker inspect redis_6382
查到我的该节点容器内 IP 为:172.17.0.10:6382
(4)将 6382 节点加入到集群中
命令:redis-cli --cluster add-node 172.17.0.10:6382 172.17.0.5:6380
该命令将 6382节点加入到集群中,默认是主节点,见下图:
查询集群节点信息。命令:cluster nodes
上图表示该节点已加入集群,并且是主节点。
(5 )为 6382 节点分配 2500 个 slot
当前,6382 节点虽然已加入集群,但是没有 slot 插槽,不能使用,所以还需要为它分配插槽。
命令:redis-cli --culuster reshard 集群中任一节点的 IP
参数说明:
reshard:在集群中重新分配 slot 插槽
如:要将节点 6380 的 2500 个 slot 分配给节点 6382,在任一节点容器内执行以下命令:
redis-cli --cluster reshard 172.17.0.5:6380
输入 2500 和 6382 节点的 node id,表示分配给 6382 节点 2500 个 slot。具体见下图:
指定 source node 为 6380 的 node id,表示从 6380 上拿走 2500 个 slot。输入“done”后,开始移动 slot,直到移动完毕。
(6) 查询集群节点信息
可以发现,6380 和 6382 上的插槽都有变化,slot 分配成功。
这时,集群的扩容完成。因数据是绑定在插槽上的,所以插槽移动了,数据也随着
移动。
3. 集群的故障转移
Redis 的分片集群中,自带哨兵机制,所以处理故障转移方便快捷。假设模拟 6380 节点出现了故障。下图是集群正常和出现故障时各节点信息截图,可以看出,6380 节点出现故障时,集群检测到了该节点状态为“fail”;
先查看集群正常,没出现故障时的各节点信息截图:
可以看到:
6381、6382、26380、6380节点为主节点,6379、26381、26379节点为从节点
其中,26381节点为6380节点的从节点
下面停止6380节点对应的容器redis_6380模拟故障:
可以看出,6380 节点出现故障时,集群检测到了该节点状态为“fail”:
然后,集群会自动将 6380节点的从节点 26381 提升为主节点;
将redis_6382容器重新启动:
可以看出:当 6380 节点重新启动后,它成为 26381 节点的从节点。