准备工作 创建 工作空间
mkdir -p /usr/local/redis_cluster
下载相应的软件:
wget http://download.redis.io/releases/redis-4.0.1.tar.gz
yum install -y gcc-c++
解压安装包 并 编译
tar -vxf redis-4.0.1.tar.gz
cd redis-4.0.1
make
修改配置文件
将守护进程yes改成no daemonize no
ip绑定 bind 0.0.0.0
设置密码 requirepass 123456789
主从复制的验证密码 masterauth 123456789
日志文件 logfile "/usr/local/redis/logs/redis-server.log"
开启集群配置 cluster-enabled yes
集群配置文件 cluster-config-file nodes-6379.conf
集群超时时间 cluster-node-timeout 15000
==========================================================================
redis基础镜像的创建
vi Dockerfile
# Redis
# Version 4.0.1
#指定基础镜像 当前镜像非可执行镜像,所以没有包含ENTRYPOINT和CMD指令
FROM centos:7
#镜像作者
MAINTAINER xcl "lansekaola@163.com"
#定义路径的环境变量
ENV REDIS_HOME /usr/local
#本地的redis源码包复制到镜像的根路径下,ADD命令会在复制过后自动解包。
#被复制的对象必须处于Dockerfile同一路径,且ADD后面必须使用相对路径
#将Dockerfile同级目录下的redis-4.0.1.tar.gz复制到镜像的根目录
ADD redis-4.0.1.tar.gz /
#创建安装目录,根据环境变量信息,实际的创建目录为:/usr/local/redis
RUN mkdir -p $REDIS_HOME/redis
#将一开始编译产生并修改后的配置复制到安装目录
ADD redis-4.0.1/redis.conf $REDIS_HOME/redis/
#更新镜像的yum
RUN yum -y update
#安装编译需要的工具
RUN yum install -y gcc make
#指定工作目录
WORKDIR /redis-4.0.1
#执行编译
RUN make
#移动编译后的redis-server到容器相关的目录
#编译后,容器中只需要可执行文件redis-server
RUN mv /redis-4.0.1/src/redis-server $REDIS_HOME/redis/
#移动到上一级
WORKDIR /
#删除解压文件
RUN rm -rf /redis-4.0.1
#安装编译完成之后,可以删除多余的gcc跟make
RUN yum remove -y gcc make
#添加数据卷
#此目录需要和redis.conf中logfile一致
#/usr/local/redis/logs/redis-server.log
VOLUME ["/usr/local/redis/logs"]
#暴露6379的端口
EXPOSE 6379
===============================================================================
构建镜像 注意,后面还有一个. 这个.表示当前目录下的Dockerfile
docker build -t xcl/redis-cluster .
└─[$] <> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
xcl/redis-cluster latest 4772f4f77453 About a minute ago 647MB
centos 7 67fa590cfc1c 2 months ago 202MB
创建Redis节点镜像
vi Dockerfile
# Redis Node
# Version 4.0.1
FROM xcl/redis-cluster:latest
MAINTAINER xcl "lansekaola@163.com"
#指定容器启动程序及参数
ENTRYPOINT ["/usr/local/redis/redis-server", "/usr/local/redis/redis.conf"]
构建redis节点镜像
docker build -t xcl/redis-node .
===============================================================================
└─[$] <> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
xcl/redis-node latest 5e24239cfce9 10 seconds ago 647MB
xcl/redis-cluster latest 4772f4f77453 6 minutes ago 647MB
centos 7 67fa590cfc1c 2 months ago 202MB
配置集群
1.运行redis容器
docker run -d --name redis-node-7000 -p 7000:6379 xcl/redis-node
docker run -d --name redis-node-7001 -p 7001:6379 xcl/redis-node
docker run -d --name redis-node-7002 -p 7002:6379 xcl/redis-node
docker run -d --name redis-node-7003 -p 7003:6379 xcl/redis-node
docker run -d --name redis-node-7004 -p 7004:6379 xcl/redis-node
docker run -d --name redis-node-7005 -p 7005:6379 xcl/redis-node
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cc29cc160917 xcl/redis-node "/usr/local/redis/re…" 55 seconds ago Up 54 seconds 0.0.0.0:7005->6379/tcp redis-node-7005
5c1200b759a7 xcl/redis-node "/usr/local/redis/re…" About a minute ago Up About a minute 0.0.0.0:7004->6379/tcp redis-node-7004
b50ccbcaaecc xcl/redis-node "/usr/local/redis/re…" About a minute ago Up About a minute 0.0.0.0:7003->6379/tcp redis-node-7003
cb4843b7e73b xcl/redis-node "/usr/local/redis/re…" About a minute ago Up About a minute 0.0.0.0:7002->6379/tcp redis-node-7002
df2935e00b99 xcl/redis-node "/usr/local/redis/re…" About a minute ago Up About a minute 0.0.0.0:7001->6379/tcp redis-node-7001
d6ce5aba983c xcl/redis-node "/usr/local/redis/re…" About a minute ago Up About a minute 0.0.0.0:7000->6379/tcp redis-node-7000
===============================================================================
docker inspect cc29cc160917 5c1200b759a7 b50ccbcaaecc cb4843b7e73b df2935e00b99 d6ce5aba983c | grep IPA
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.7",
"IPAMConfig": null,
"IPAddress": "172.17.0.7",
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.6",
"IPAMConfig": null,
"IPAddress": "172.17.0.6",
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.5",
"IPAMConfig": null,
"IPAddress": "172.17.0.5",
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.4",
"IPAMConfig": null,
"IPAddress": "172.17.0.4",
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.3",
"IPAMConfig": null,
"IPAddress": "172.17.0.3",
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.2",
"IPAMConfig": null,
"IPAddress": "172.17.0.2",
解析宿主机与容器的ip映射关系
192.168.1.92:7000 172.17.0.2:6379
192.168.1.92:7001 172.17.0.3:6379
192.168.1.92:7002 172.17.0.4:6379
192.168.1.92:7003 172.17.0.5:6379
192.168.1.92:7004 172.17.0.6:6379
192.168.1.92:7005 172.17.0.7:6379
===============================================================================
CLUSTER FAILOVER
//集群(cluster)
CLUSTER INFO 打印集群的信息
CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相关信息。
//节点(node)
CLUSTER MEET <ip> <port> 将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
CLUSTER FORGET <node_id> 从集群中移除 node_id 指定的节点。
CLUSTER REPLICATE <node_id> 将当前节点设置为 node_id 指定的节点的从节点。
CLUSTER SAVECONFIG 将节点的配置文件保存到硬盘里面。
//槽(slot)
CLUSTER ADDSLOTS <slot> [slot ...] 将一个或多个槽(slot)指派(assign)给当前节点。
CLUSTER DELSLOTS <slot> [slot ...] 移除一个或多个槽对当前节点的指派。
CLUSTER FLUSHSLOTS 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
CLUSTER SETSLOT <slot> NODE <node_id> 将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,
那么先让另一个节点删除该槽>,然后再进行指派。
CLUSTER SETSLOT <slot> MIGRATING <node_id> 将本节点的槽 slot 迁移到 node_id 指定的节点中。
CLUSTER SETSLOT <slot> IMPORTING <node_id> 从 node_id 指定的节点中导入槽 slot 到本节点。
CLUSTER SETSLOT <slot> STABLE 取消对槽 slot 的导入(import)或者迁移(migrate)。
//键 (key)
CLUSTER KEYSLOT <key> 计算键 key 应该被放置在哪个槽上。
CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的键值对数量。
CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 个 slot 槽中的键。
===============================================================================
节点配置
Redis Cluster 的集群感知操作
redis 集群感知:节点握手——是指一批运行在集群模式的节点通过Gossip协议彼此通信,达到感知对方的过程。
任意进入一个redis
将以下所有的redis服务都添加到redis集群的节点
./redis-cli -p 7000
127.0.0.1:7000> auth 123456789
OK
127.0.0.1:7000> info replication
# Replication
role:master
connected_slaves:0
master_replid:3384d18e4e0b51e211b3b96d08c7ae8003e45046
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
客户连接之后,因为之前设置了密码,所以需要先输入密码认证,否则就无法通过
所有的redis都是master角色 role:master
127.0.0.1:7000> CLUSTER MEET 172.17.0.3 6379
OK
127.0.0.1:7000> CLUSTER MEET 172.17.0.4 6379
OK
127.0.0.1:7000> CLUSTER MEET 172.17.0.5 6379
OK
127.0.0.1:7000> CLUSTER MEET 172.17.0.6 6379
OK
127.0.0.1:7000> CLUSTER MEET 172.17.0.7 6379
OK
127.0.0.1:7000> CLUSTER NODES
268d72f0c226b7223e86c9afbb8cc9c67405a3ed 172.17.0.5:6379@16379 master - 0 1572739906997 3 connected
5e3c52d5a4232b937588d2ee7c6b3d667e9ae60d 172.17.0.6:6379@16379 master - 0 1572739904000 4 connected
aa1f8bcadcc2b571366f7b5a6326659d703cc32a 172.17.0.3:6379@16379 master - 0 1572739905000 1 connected
9f8af65badd4675970a72cccc3f42f4617ee8851 172.17.0.7:6379@16379 master - 0 1572739906000 5 connected
c54902379b775e01b25abc5dc6d446389908f653 172.17.0.2:6379@16379 myself,master - 0 1572739904000 0 connected
6ba512ca78a601d4f38dfe152dbd8646810c0a6d 172.17.0.4:6379@16379 master - 0 1572739905992 2 connected
当前已经使这六个节点组成集群,但是现在还无法工作,因为集群节点还没有分配槽(slot)。
127.0.0.1:7000> CLUSTER INFO
cluster_state:fail
cluster_slots_assigned:0 # 被分配槽的个数为0
cluster_slots_ok:0
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:0
cluster_current_epoch:5
cluster_my_epoch:0
cluster_stats_messages_ping_sent:179
cluster_stats_messages_pong_sent:198
cluster_stats_messages_meet_sent:5
cluster_stats_messages_sent:382
cluster_stats_messages_ping_received:198
cluster_stats_messages_pong_received:184
cluster_stats_messages_received:382
上面看到集群状态是失败的,原因是槽位没有分配,而且需要一次性把16384个槽位完全分配了,集群才可用。
=================================================================================================================
分配槽位: CLUSTER ADDSLOTS 槽位,一个槽位只能分配一个节点,16384个槽位必须分配完,不同节点不能冲突。
所以通过脚本进行分配 addslots.sh:
#!/bin/bash
#将0-5461 的槽点配置在 172.17.0.2:6379 (宿主机7000) 的redis上
n=0
for ((i=n;i<=5461;i++))
do
/usr/local/redis_cluster/redis-4.0.1/src/redis-cli -p 7000 -a 123456789 CLUSTER ADDSLOTS $i
done
#将5462-10922的槽点配置在 172.17.0.3:6379 (宿主机7001) 的redis上
n=5462
for ((i=n;i<=10922;i++))
do
/usr/local/redis_cluster/redis-4.0.1/src/redis-cli -p 7001 -a 123456789 CLUSTER ADDSLOTS $i
done
#将10923-16383的槽点配置在 172.17.0.4:6379 (宿主机7002) 的redis上
n=10923
for ((i=n;i<=16383;i++))
do
/usr/local/redis_cluster/redis-4.0.1/src/redis-cli -p 7002 -a 123456789 CLUSTER ADDSLOTS $i
done
保存后 改成 可执行文件
chmod 777 addslots.sh
执行脚本
=================================================================================================================
127.0.0.1:7000> CLUSTER INFO
cluster_state:ok # 集群状态为失败
cluster_slots_assigned:16384 # 已经全部分配完成 一定要等到脚本执行 完全
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6 # 总共6个节点
cluster_size:3 # 集群为 3 个节点
cluster_current_epoch:5
cluster_my_epoch:0
cluster_stats_messages_ping_sent:955
cluster_stats_messages_pong_sent:988
cluster_stats_messages_meet_sent:5
cluster_stats_messages_sent:1948
cluster_stats_messages_ping_received:988
cluster_stats_messages_pong_received:960
cluster_stats_messages_received:1948
以上我们已经搭建了一套完整的可运行的redis cluster,但是每个节点都是单点,
这样子可能出现,一个节点挂掉,整个集群因为槽位分配不完全而崩溃,
因此,我们需要为每个节点配置副本备用节点。
前面我们已经提前创建了6个备用节点,搭建集群花了三个,因此还有剩下三个直接可以用来做备用副本。
查看所有节点的id
127.0.0.1:7000> CLUSTER NODES
268d72f0c226b7223e86c9afbb8cc9c67405a3ed 172.17.0.5:6379@16379 master - 0 1572740973000 3 connected
5e3c52d5a4232b937588d2ee7c6b3d667e9ae60d 172.17.0.6:6379@16379 master - 0 1572740975861 4 connected
aa1f8bcadcc2b571366f7b5a6326659d703cc32a 172.17.0.3:6379@16379 master - 0 1572740971000 1 connected 5462-10922
9f8af65badd4675970a72cccc3f42f4617ee8851 172.17.0.7:6379@16379 master - 0 1572740974000 5 connected
c54902379b775e01b25abc5dc6d446389908f653 172.17.0.2:6379@16379 myself,master - 0 1572740975000 0 connected 0-5461
6ba512ca78a601d4f38dfe152dbd8646810c0a6d 172.17.0.4:6379@16379 master - 0 1572740974851 2 connected 10923-16383
编写脚本,添加副本节点
vi addSlaveNodes.sh
#!/bin/bash
/usr/local/redis_cluster/redis-4.0.1/src/redis-cli -p 7003 -a 123456789 CLUSTER REPLICATE c54902379b775e01b25abc5dc6d446389908f653
/usr/local/redis_cluster/redis-4.0.1/src/redis-cli -p 7004 -a 123456789 CLUSTER REPLICATE aa1f8bcadcc2b571366f7b5a6326659d703cc32a
/usr/local/redis_cluster/redis-4.0.1/src/redis-cli -p 7005 -a 123456789 CLUSTER REPLICATE 6ba512ca78a601d4f38dfe152dbd8646810c0a6d
注意:1、作为备用的节点,必须是未分配槽位的,否者会操作失败 (error) ERR To set a master the node must be empty and without assigned slots 。
2、需要从 需要添加的节点上面执行操作,CLUSTER REPLICATE [node_id] ,使当前节点成为 node_id 的副本节点。
3、添加从节点(集群复制): 复制的原理和单机的Redis复制原理一样,区别是:集群下的从节点也需要运行在 cluster 模式下,要先添加到集群里面,再做复制。
保存后 改成 可执行文件
chmod 777 addSlaveNodes.sh
执行脚本
./addSlaveNodes.sh
OK
OK
OK
127.0.0.1:7000> CLUSTER NODES
268d72f0c226b7223e86c9afbb8cc9c67405a3ed 172.17.0.5:6379@16379 slave c54902379b775e01b25abc5dc6d446389908f653 0 1572741580507 3 connected
5e3c52d5a4232b937588d2ee7c6b3d667e9ae60d 172.17.0.6:6379@16379 slave aa1f8bcadcc2b571366f7b5a6326659d703cc32a 0 1572741582533 4 connected
aa1f8bcadcc2b571366f7b5a6326659d703cc32a 172.17.0.3:6379@16379 master - 0 1572741581526 1 connected 5462-10922
9f8af65badd4675970a72cccc3f42f4617ee8851 172.17.0.7:6379@16379 slave 6ba512ca78a601d4f38dfe152dbd8646810c0a6d 0 1572741583000 5 connected
c54902379b775e01b25abc5dc6d446389908f653 172.17.0.2:6379@16379 myself,master - 0 1572741581000 0 connected 0-5461
6ba512ca78a601d4f38dfe152dbd8646810c0a6d 172.17.0.4:6379@16379 master - 0 1572741583541 2 connected 10923-16383
可以看到我们现在实现了三主三从的一个高可用集群。
集群测试:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cc29cc160917 xcl/redis-node "/usr/local/redis/re…" 46 minutes ago Up 46 minutes 0.0.0.0:7005->6379/tcp redis-node-7005
5c1200b759a7 xcl/redis-node "/usr/local/redis/re…" 46 minutes ago Up 46 minutes 0.0.0.0:7004->6379/tcp redis-node-7004
b50ccbcaaecc xcl/redis-node "/usr/local/redis/re…" 46 minutes ago Up 46 minutes 0.0.0.0:7003->6379/tcp redis-node-7003
cb4843b7e73b xcl/redis-node "/usr/local/redis/re…" 46 minutes ago Up 46 minutes 0.0.0.0:7002->6379/tcp redis-node-7002
df2935e00b99 xcl/redis-node "/usr/local/redis/re…" 46 minutes ago Up 46 minutes 0.0.0.0:7001->6379/tcp redis-node-7001
d6ce5aba983c xcl/redis-node "/usr/local/redis/re…" 46 minutes ago Up 46 minutes 0.0.0.0:7000->6379/tcp redis-node-7000
docker stop cb4843b7e73b
尝试关闭一个master,选择端口为 7002 的容器,停掉之后:
自动故障转移正常
127.0.0.1:7000> CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:5 #当前节点数为5了
cluster_my_epoch:0
cluster_stats_messages_ping_sent:1900
cluster_stats_messages_pong_sent:1937
cluster_stats_messages_meet_sent:5
cluster_stats_messages_sent:3842
cluster_stats_messages_ping_received:1937
cluster_stats_messages_pong_received:1902
cluster_stats_messages_received:3839
127.0.0.1:7000> CLUSTER NODES
268d72f0c226b7223e86c9afbb8cc9c67405a3ed 172.17.0.5:6379@16379 slave c54902379b775e01b25abc5dc6d446389908f653 0 1572742433000 3 connected
5e3c52d5a4232b937588d2ee7c6b3d667e9ae60d 172.17.0.6:6379@16379 slave aa1f8bcadcc2b571366f7b5a6326659d703cc32a 0 1572742432091 4 connected
aa1f8bcadcc2b571366f7b5a6326659d703cc32a 172.17.0.3:6379@16379 master - 0 1572742434136 1 connected 5462-10922
9f8af65badd4675970a72cccc3f42f4617ee8851 172.17.0.7:6379@16379 master - 0 1572742433115 6 connected 10923-16383
c54902379b775e01b25abc5dc6d446389908f653 172.17.0.2:6379@16379 myself,master - 0 1572742431000 0 connected 0-5461
6ba512ca78a601d4f38dfe152dbd8646810c0a6d 172.17.0.4:6379@16379 slave,fail 9f8af65badd4675970a72cccc3f42f4617ee8851 1572742307745 1572742305617 6 connected
4主节点 失败后 它对应的 从节点 7 自动升级为主节点
再次启动容器后 ====127.0.0.1:7000> CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6 #当前节点数为6了
cluster_my_epoch:0
cluster_stats_messages_ping_sent:2245
cluster_stats_messages_pong_sent:2186
cluster_stats_messages_meet_sent:5
cluster_stats_messages_fail_sent:5
cluster_stats_messages_auth-ack_sent:1
cluster_stats_messages_update_sent:1
cluster_stats_messages_sent:4443
cluster_stats_messages_ping_received:2186
cluster_stats_messages_pong_received:2175
cluster_stats_messages_fail_received:1
cluster_stats_messages_auth-req_received:1
cluster_stats_messages_received:4363