集群搭建
基于 docker
在我们云服务器上搭建出一个 redis
集群出来
当前节点,主要是因为我们只有一个云服务器,搞分布式系统,就比较麻烦。实际工作中,一般是通过多个主机的方式,来搭建集群
- 此处我们使用
9
个docker
容器,来模拟9
台服务器
此处我们创建
11
个redis
节点,其中前9
个用来演示集群的搭建,后2
个用来演示集群扩容
一定要记得,把以前启动的 redis
容器给停掉
切换到对应目录下后,输入:
# 查看有哪些容器正在运行
docker ps -a
# 关闭此目录下的容器
docker-compose down
- 1
- 2
- 3
- 4
- 5
1. 创建目录和配置
切换到 Cluster
目录后
touch docker-compose.yml
touch generate.sh
- 1
- 2
- 3
- 在
Linux
上,以.sh
后缀结尾的文件,称为“shell 脚本”- 使用
Linux
的时候,都是通过一些命令来进行操作的。使用命令操作,就非常适合把命令给写到一个文件中,批量化执行 - 同时,还能加入:条件、循环、函数等机制。 因此,就可以基于这些来完成更复杂的工作了
- 使用
- 此处我们需要创建
11
个redis
节点,这些redis
的配置文件内容,大同小异,此时就可以使用脚本来批量生成(也可以不使用脚本,手动一个一个改)
shell
脚本:
for port in $(seq 1 9); \
do \
mkdir -p redis${port}/
touch redis${port}/redis.conf
cat << EOF > redis${port}/redis.conf
port 6379
bind 0.0.0.0
protected-mode no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.30.0.10${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
EOF
done
# 注意 cluster-announce-ip 的值有变化.
for port in $(seq 10 11); \
do \
mkdir -p redis${port}/
touch redis${port}/redis.conf
cat << EOF > redis${port}/redis.conf
port 6379
bind 0.0.0.0
protected-mode no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.30.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
EOF
done
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
for port in $(seq 1 9); \
:基于范围的循环。类似与Java
的for each
seq
就是一个Linux
命令,后面俩参数就是从哪到哪,能生成[1, 9]
这个区间
do
和done
:在shell
脚本里面,{}
用来表示变量,不是表示代码块。对于for
来说,就是使用do
和done
来表示代码块开始和结束\
:是续行符,把下一行的内容和当前行,合并成一行。shell
默认情况下,要求把所有的代码都写到一行里,所以可以使用续行符来换行- 循环体里面:
mkdir -p redis${port}/
:创建目录,名字为redis1 -> redis9
(shell
中拼接字符串是直接写到一起,而不需要使用+
)${}
是取变量的值操作
touch redis${port}/redis. conf
:创建文件。在刚才的目录基础下,创建redis.conf
cat
:进行写内容。将下面的内容,写到刚刚创建的文件中去- 文件里面大多是一样的,
cluster-announce-ip 172.30.0.10${port}
有点变化。我们通过变量来构造不同的ip
cluster-enabled yes
:开启集群cluster-config-file nodes.conf
:里面包含了一些集群的配置信息,不用我们手动写,而是redis
自动生成的(后续启动这些节点之后,会配置一些redis
集群信息)cluster-node-timeout 5000
:多个节点之间进行交互,保持联络cluster-announce-ip 172.30.0.10${port}
:该redis
节点(自己)所在主机的ip
地址(当前是使用docker
容器模拟的主机,所以此处写的是docker
容器的ip
)cluster-announce-port 6379
:redis
节点自身绑定的端口(容器内的端口),不同容器内部可以有相同端口,后续进行端口映射,再把这些容器内的端口映射到容器外的不同端口即可cluster-announce-bus-port 16379
:- 业务端口:用来进行业务数据通信。响应
redis
客户端的请求 - 管理端口:为了完成一些管理上的任务来进行通信。如果某个分片中的
redis
主节点挂了,就需要让从节点成为主节点,就需要通过刚才管理端口来完成对应的操作(Tomcat
里面,8080
是业务端口,8005
是管理端口)
- 业务端口:用来进行业务数据通信。响应
- 文件里面大多是一样的,
- 这些配置项都不用记,用到时候去查即可
预期效果:得到 11
个目录,每个目录里面都有一个配置文件,配置文件中,ip
地址各不相同
执行命令:
通过命令:
bash generate.sh
- 1
随后可以看到目录里面:
2. 编写 docker-compose.yml
version: '3.7'
networks:
mynet:
ipam:
config:
- subnet: 172.30.0.0/24
services:
redis1:
image: 'redis:5.0.9'
container_name: redis1
restart: always
volumes:
- ./redis1/:/etc/redis/
ports:
- 6371:6379
- 16371:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.101
// 剩余10个容器,格式和这个一样,将名字、端口号、ip地址递增即可
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
networks
:此处为了后续创建静态ip
,此时要先手动创建出网络,同时给这个网段也分配ip
ip 地址 = 网络号 + 主机号
。使用子网掩码的方式来区分网络号和主机号- 这里的
/24
就代表子网掩码左边24
位都是1
,右边8
位是0
,255.255.255.0
,网络号就是172.30.0
ip
是内网 ip- 配置的网络号不能和当前主机上现有的其他网段冲突(每个人的主机上已有的网段,具体不一定一样,
ifconfig
)
- 后面就是常规操作,配置容器
ports
:此处不进行端口映射,也是可以的,映射一下目的是为了在容器外面通过客户端直接进行访问- 静态 ip 配置,网络号部分要和前面的网段一致,主机号部分,可以随便配置(
1-255
,保证不重复),按照之前在配置文件中写的101-111
这11
台主机
进行上述配置的时候,一定要保证前后一致性(第一步和第二部相关部分,端口号、ip 地址)
完整配置文件
version: '3.7'
networks:
mynet:
ipam:
config:
- subnet: 172.30.0.0/24
services:
redis1:
image: 'redis:5.0.9'
container_name: redis1
restart: always
volumes:
- ./redis1/:/etc/redis/
ports:
- 6371:6379
- 16371:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.101
redis2:
image: 'redis:5.0.9'
container_name: redis2
restart: always
volumes:
- ./redis2/:/etc/redis/
ports:
- 6372:6379
- 16372:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.102
redis3:
image: 'redis:5.0.9'
container_name: redis3
restart: always
volumes:
- ./redis3/:/etc/redis/
ports:
- 6373:6379
- 16373:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.103
redis4:
image: 'redis:5.0.9'
container_name: redis4
restart: always
volumes:
- ./redis4/:/etc/redis/
ports:
- 6374:6379
- 16374:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.104
redis5:
image: 'redis:5.0.9'
container_name: redis5
restart: always
volumes:
- ./redis5/:/etc/redis/
ports:
- 6375:6379
- 16375:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.105
redis6:
image: 'redis:5.0.9'
container_name: redis6
restart: always
volumes:
- ./redis6/:/etc/redis/
ports:
- 6376:6379
- 16376:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.106
redis7:
image: 'redis:5.0.9'
container_name: redis7
restart: always
volumes:
- ./redis7/:/etc/redis/
ports:
- 6377:6379
- 16377:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.107
redis8:
image: 'redis:5.0.9'
container_name: redis8
restart: always
volumes:
- ./redis8/:/etc/redis/
ports:
- 6378:6379
- 16378:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.108
redis9:
image: 'redis:5.0.9'
container_name: redis9
restart: always
volumes:
- ./redis9/:/etc/redis/
ports:
- 6379:6379
- 16379:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.109
redis10:
image: 'redis:5.0.9'
container_name: redis10
restart: always
volumes:
- ./redis10/:/etc/redis/
ports:
- 6380:6379
- 16380:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.110
redis11:
image: 'redis:5.0.9'
container_name: redis11
restart: always
volumes:
- ./redis11/:/etc/redis/
ports:
- 6381:6379
- 16381:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.111
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
3. 启动容器
启动之前,一定要把之前已经运行的 redis
相关东西都干掉!否则就可能因为端口冲突等原因,导致现在的启动失败
通过下面命令启动
docker-compose up -d
- 1
4. 构建集群
此处把前
9
个主机构建成集群,3
主6
从,后2
个主机暂时不用
相关命令:
redis-cli --cluster create 172.30.0.101:6379 172.30.0.102:6379 172.30.0.103:6379 172.30.0.104:6379 172.30.0.105:6379 172.30.0.106:6379 172.30.0.107:6379 172.30.0.108:6379 172.30.0.109:6379 --cluster-replicas 2
- 1
--cluster create
:建立集群,后面填写每个节点的 ip 和地址--cluster-replicas 2
:表示每个主节点要两个从节点备份- 这个配置设置之后,
redis
就知道了,3
个节点是一伙的,一共3
个分片
- 这个配置设置之后,
redis
在构建集群的时候,谁是主节点,谁是从节点,谁和谁是一个分片,都是不固定的
- 本身从集群的角度来看,提供的这些节点之间本来就应该是等价的
命令执行完之后
- 分片信息、槽位信息、主从节点信息… 都给出了
- 最后需要手动输入“
yes
”进行构建
超时
如果在输入构建命令连接不上,超时,就需要进行一步处理
在进行构建集群操作之前,需要先让这个命令在任意一个 redis
容器中进行
- 所有的
redis
容器都是在同一个局域网内,但是此时这个宿主机却不在,想要进行后续操作,就必须要保证都在同一个局域网内 - 在容器内进行构建集群的操作,就能保证都是在同一个局域网内了
执行命令
docker exec -it ce /bin/bash
- 1
docker exec
:在一个已经运行中的docker
容器内执行命令-it
:-i
:表示以交互模式运行,让能够保持输入流打开-t
:分配一个“伪终端”(TTY),这样你可以像在普通终端中一样与容器交互
ce
:容器的名字或容器 ID,表示要进入的容器bin/bash
:表示在容器内部启动一个Bash shell
,通常用于容器内操作
在集群构建完毕之后,输入 exit
就可以退出容器
- 生成每个
redis
节点的配置文件 - 使用
docker
创建出11
个redis
节点,并且启动容器 - 使用
redis-cli
执行构建集群命令

一起努力,一起进步!
微信名片


评论记录:
回复评论: