【那些年我们用过的Redis】Redis集群搭建原来这么简单
Reids服务集群模式可分为主从、哨兵、Cluster模式。本博客主要介绍主从和Cluster模式
三种集群模式简介
主从模式
:主从模式是三种模式中最简单的,一般有一个master
服务和多个(至少一个)slave
服务组成。主要实现读写分离,减轻单Redis服务压力。master
负责写数据,然后将数据copy给slave
,slave
服务负责读数据。
哨兵模式
:主从模式有个弊端,就是一旦master
服务挂掉,Redis服务就无法再写入数据,slave
并不会升级为master
。于是需要另外一种类型的服务Sentinel
(哨兵)。Sentinel
主要负责监控
、通知
、自动故障转移
、配置提供者
。简单来说就是,Sentinel
可以监督数据节点(master
和slave
)健康状态,并通知DBA(数据库管理人员),如果master
挂了,从众多slave
中选举一个新的master
,并且告诉客户端(cli)数据节点的信息。
Cluster
:哨兵模式虽然相较于主从模式来说,友善了很多,但是master
不好做负载,并且储存受单机限制,还引入了另外一种类型的服务,有些繁琐。于是乎,Cluster
就来了,通常具有 高可用、可扩展性、分布式、容错 等特性。当然,Cluster
和哨兵模式
没有明确的谁好谁坏,还是要看自己的需求的。一般分布式,使用Cluster
好一些。
主从模式
在搭建主从模式
和Cluster
之前,我默认你会安装单机的redis,并且你的环境是Linux(CentOS7),你的Redis版本是5.0.9。如果不会单机redis安装,请戳。
首先将原生的redis.conf
复制两份到/usr/local
路径下:
cp redis.conf /usr/local/redis_master.conf
cp redis.conf /usr/local/redis_replic.conf
然后利用vim
修改两个配置文件,修改主要参数如下:
redis_master.conf
# 主机地址,默认是127.0.0.1,修改成0.0.0.0
bind 0.0.0.0
# 端口
port 16379
# 是否开启为守护线程,默认是no,改成yes
daemonize yes
# 指定redis进程的PID文件存放位置 给文件重命名
pidfile /var/run/redis_16379.pid
# 日志存放位置 给文件重命名
logfile /var/log/redis_16379.log
# rdb模式持久化快照
dbfilename dump-16379.rdb
# 持久化文件存放位置
dir ./redis-workir
# redis连接密码
requirepass 123456
# 连接主服务器的密码,这里可以省略
masterauth 123456
redis_replic.conf
# 主机地址,默认是127.0.0.1,修改成0.0.0.0
bind 0.0.0.0
# 端口
port 26379
# 是否开启为守护线程,默认是no,改成yes
daemonize yes
# 指定redis进程的PID文件存放位置 给文件重命名
pidfile /var/run/redis_26379.pid
# 日志存放位置 给文件重命名
logfile /var/log/redis_26379.log
# rdb模式持久化快照
dbfilename dump-26379.rdb
# 持久化文件存放位置
dir ./redis-workir
# redis连接密码
requirepass 123456
# 连接主服务器的密码
masterauth 123456
# 本复制节点的主节点地址
replicaof 你服务器外网ip 16379
上面注意,在之前的版本replicaof
叫做slaveof
。这里,我们模仿有两台主机,所以主机ip不写127.0.0.1
了,写你服务器外网的ip,后面也方便说下网关的问题。然后开启两个服务。
redis-server /usr/local/redis_master.conf
redis-server /usr/local/redis_replic.conf
此时查看两个服务日志,都成长启动了。但是此时master,写数据,slave
无法复制数据,查看日志报错
Error condition on socket for SYNC: No route to host
这边需要打开服务器的防火墙,用到iptables
,安装请移步我上篇博客(请戳)。
iptables -I INPUT -p tcp -m tcp --dport 16379 -j ACCEPT
iptables -I INPUT -p tcp -m tcp --dport 26379 -j ACCEPT
service iptables save
# 查看一下
iptables -L -n -v
# 的确暴露出去这两个端口了
66 3528 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:26379
196K 17M ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:16379
然后使用一下
[root@VM_0_10_centos ~]# redis-cli -h 127.0.0.1 -p 16379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:16379> set today 1106
OK
127.0.0.1:16379>
[root@VM_0_10_centos ~]# redis-cli -h 127.0.0.1 -p 26379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:26379> get today
"1106"
Cluster模式
首先我们创建一个文件夹/usr/local/redis-cluster
。并在它下面创建log
、data
、conf
,并在data
文件中创建不同服务的文件夹。基本就是cd
到位置,然后使用mkdir
,比较简单,就看下目录结构吧
[root@VM_0_10_centos redis-cluster]# tree -d
.
|-- conf
|-- data
| |-- redis-6378
| |-- redis-6380
| |-- redis-6381
| |-- redis-6389
| |-- redis-6390
| |-- redis-6391
`-- log
然后在conf
文件下创建这几个服务的配置文件,这几个文件,一摸一样,只需要关键位置替换端口号就好了,你懂的,下面以6378为例。
cd /usr/local/redis-cluster/conf
# copy一份原始文件过来
cp /usr/local/redis.conf /usr/local/redis-cluster/conf/redis-6378.conf
vim redis-6378.conf
修改关键配置如下,其他默认不变
redis-6378.conf
# 主机地址,默认是127.0.0.1,修改成0.0.0.0
bind 0.0.0.0
# 端口
port 6378
# 是否开启为守护线程,默认是no,改成yes
daemonize yes
# 指定redis进程的PID文件存放位置 给文件重命名
pidfile /var/run/redis-cluster/redis-6378.pid
# 日志存放位置 给文件重命名
logfile /usr/local/redis-cluster/log/redis-6378.log
# rdb模式持久化快照
dbfilename dump-6378.rdb
# 持久化文件存放位置
dir /usr/local/redis-cluster/data/redis-6378
# redis连接密码
requirepass 123456
# 连接主服务器的密码
masterauth 123456
# 开启AOF持久化模式
appendonly yes
# 开启cluster集群模式
cluster-enabled yes
# 集群的配置,配置文件首次启动自动生成
cluster-config-file /usr/local/redis-cluster/conf/node-6378.conf
# 请求超时,默认的就好
cluster-node-timeout 15000
cluster-enabled
开启cluster
集群模式,appendonly
开启AOF持久化模式,一种实时性比RDB
模式更好的持久化模式。生成的aof
格式文件也在dir
路径下,并且被读进内存的优先级比dump-6378.rdb
文件要高。cluster-config-file
是存放集群配置文件的地方,自动生成。同样的配置,将端口号换成其他五个,生成redis-6380.conf
、redis-6381.conf
、redis-6389.conf
、redis-6390.conf
、redis-6391.conf
。然后开启这些服务。
redis-server redis-6378.conf
redis-server redis-6380.conf
redis-server redis-6381.conf
redis-server redis-6389.conf
redis-server redis-6390.conf
redis-server redis-6391.conf
# 查看下是否开启
ps -ef | grep redis
# 进程已存在
root 3009 1 0 Nov05 ? 00:01:49 redis-server 0.0.0.0:6378 [cluster]
root 3047 1 0 Nov05 ? 00:01:47 redis-server 0.0.0.0:6381 [cluster]
root 3056 1 0 Nov05 ? 00:01:50 redis-server 0.0.0.0:6389 [cluster]
root 3073 1 0 Nov05 ? 00:01:49 redis-server 0.0.0.0:6390 [cluster]
root 3083 1 0 Nov05 ? 00:01:50 redis-server 0.0.0.0:6391 [cluster]
root 26443 1 0 Nov05 ? 00:01:39 redis-server 0.0.0.0:6380 [cluster]
注意,它们后面都显示它们是以cluster
集群形式开启的。下面开启集群,如果是redis5.0以前的版本,需要下载ruby,通过ruby开启,redis5.0以后可直接开启,命令如下:
# 开启集群
redis-cli -a 123456--cluster create 127.0.0.1:6378 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6389 127.0.0.1:6390 127.0.0.1:6391 --cluster-replicas 1
# 会多一步询问,输入yes即可
Can I set the above configuration? (type 'yes' to accept): yes
#开启代理防火墙
iptables -I INPUT -p tcp -m tcp --dport 6378 -j ACCEPT
iptables -I INPUT -p tcp -m tcp --dport 6380 -j ACCEPT
iptables -I INPUT -p tcp -m tcp --dport 6381 -j ACCEPT
iptables -I INPUT -p tcp -m tcp --dport 6389 -j ACCEPT
iptables -I INPUT -p tcp -m tcp --dport 6390 -j ACCEPT
iptables -I INPUT -p tcp -m tcp --dport 6391 -j ACCEPT
service iptables save
开启集群的命令,会自动生成主从关系,分配solt
,终端会询问这种分配方式ok吗?如果操作者觉得可以的话,需要输入yes
。用cli方式随便连接一个redis服务。
redis-cli -c -h 127.0.0.1 -p 6378 -a 123456
127.0.0.1:6378> CLUSTER INFO
# 此处省略一些信息
127.0.0.1:6378> CLUSTER NODES
114d082bb43c67042c806e0060f5fb8157736b98 127.0.0.1:6390@16390 slave ca998854f1d96e2b64b7304aea5e5b4c96a9d85a 0 1604672507350 5 connected
1efc0139a5422c68f1c43428d1d6f566ce361fed 127.0.0.1:6378@16378 myself,master - 0 1604672504000 1 connected 0-5460
f10fc263b1b887fe175307b2fb7600370d39c0e1 127.0.0.1:6389@16389 master - 0 1604672505000 8 connected 5461-10922
e1eb98ead97d9b22fe4538601cbcd193e998baad 127.0.0.1:6380@16380 slave f10fc263b1b887fe175307b2fb7600370d39c0e1 0 1604672505347 8 connected
ca998854f1d96e2b64b7304aea5e5b4c96a9d85a 127.0.0.1:6381@16381 master - 0 1604672506000 3 connected 10923-16383
0f75c7f994a43551671e955a9f72c28a9c6edb56 127.0.0.1:6391@16391 slave 1efc0139a5422c68f1c43428d1d6f566ce361fed 0 1604672504344 6 connected
可以看出6378
、6389
、6381
是master
节点,分别管理卡槽0-5460
、5461-10922
、10923-16383
。并且可以根据id值,判断出三个slave
节点的主节点是谁,例如6390
主节点id值是ca998854f1d96e2b64b7304aea5e5b4c96a9d85a
,所以就是6381
了。
这里需要说明一下,当我们存值的时候,key会根据hash函数计算出来,落在那个卡槽上。
127.0.0.1:6378> set haha 123
OK
127.0.0.1:6378> set name pjjlt
-> Redirected to slot [5798] located at 127.0.0.1:6389
OK
127.0.0.1:6389>
可以看出来,haha经过hash运算,落在的卡槽在0-5460范围内,name经过hash运算,落在的卡槽在5461-10922范围内,所以服务终端也自动重定向到6389服务上。get也会导致服务终端重定向。
127.0.0.1:6389> get name
"pjjlt"
127.0.0.1:6389> get haha
-> Redirected to slot [3662] located at 127.0.0.1:6378
"123"
127.0.0.1:6378>
增加和移除节点
cluster集群可以友好的水平拓展。下面增加两个节点,同上面一样,增加配置文件redis-6395.conf
、redis-6396.conf
,并开启这两个服务
redis-server redis-6395.conf
redis-server redis-6396.conf
加入集群
# 随便连接一个服务
redis-cli -c -h 127.0.0.1 -p 6378 -a 123456
# 加入集群
CLUSTER MEET 127.0.0.1 6395
CLUSTER MEET 127.0.0.1 6395
# 查看状态
CLUSTER NODES
114d082bb43c67042c806e0060f5fb8157736b98 127.0.0.1:6390@16390 slave ca998854f1d96e2b64b7304aea5e5b4c96a9d85a 0 1604673986000 5 connected
1efc0139a5422c68f1c43428d1d6f566ce361fed 127.0.0.1:6378@16378 myself,master - 0 1604673985000 1 connected 0-5460
2eefbdc56047282fc80baf3cc7bc08ff86dbdf9e 127.0.0.1:6395@16395 master - 0 1604673985000 7 connected
f10fc263b1b887fe175307b2fb7600370d39c0e1 127.0.0.1:6389@16389 master - 0 1604673988720 8 connected 5461-10922
e1eb98ead97d9b22fe4538601cbcd193e998baad 127.0.0.1:6380@16380 slave f10fc263b1b887fe175307b2fb7600370d39c0e1 0 1604673987717 8 connected
f8c884f07375cb524236341c4fcb963f58f82622 127.0.0.1:6396@16396 master - 0 1604673987517 7 connected
ca998854f1d96e2b64b7304aea5e5b4c96a9d85a 127.0.0.1:6381@16381 master - 0 1604673986000 3 connected 10923-16383
0f75c7f994a43551671e955a9f72c28a9c6edb56 127.0.0.1:6391@16391 slave 1efc0139a5422c68f1c43428d1d6f566ce361fed 0 1604673986716 6 connected
可以看出,此时加入的两个节点全都是master
服务,现在将6396设置成6395的slave节点。
redis-cli -c -h 127.0.0.1 -p 6396 -a 123456 cluster replicate 2eefbdc56047282fc80baf3cc7bc08ff86dbdf9e
# 随便连接一个服务
redis-cli -c -h 127.0.0.1 -p 6378 -a 123456
CLUSTER NODES
114d082bb43c67042c806e0060f5fb8157736b98 127.0.0.1:6390@16390 slave ca998854f1d96e2b64b7304aea5e5b4c96a9d85a 0 1604673986000 5 connected
1efc0139a5422c68f1c43428d1d6f566ce361fed 127.0.0.1:6378@16378 myself,master - 0 1604673985000 1 connected 0-5460
2eefbdc56047282fc80baf3cc7bc08ff86dbdf9e 127.0.0.1:6395@16395 master - 0 1604673985000 7 connected
f10fc263b1b887fe175307b2fb7600370d39c0e1 127.0.0.1:6389@16389 master - 0 1604673988720 8 connected 5461-10922
e1eb98ead97d9b22fe4538601cbcd193e998baad 127.0.0.1:6380@16380 slave f10fc263b1b887fe175307b2fb7600370d39c0e1 0 1604673987717 8 connected
f8c884f07375cb524236341c4fcb963f58f82622 127.0.0.1:6396@16396 slave 2eefbdc56047282fc80baf3cc7bc08ff86dbdf9e 0 1604673987517 7 connected
ca998854f1d96e2b64b7304aea5e5b4c96a9d85a 127.0.0.1:6381@16381 master - 0 1604673986000 3 connected 10923-16383
0f75c7f994a43551671e955a9f72c28a9c6edb56 127.0.0.1:6391@16391 slave 1efc0139a5422c68f1c43428d1d6f566ce361fed 0 1604673986716 6 connected
可以看出,此时6396节点已经变成了6395的slave节点了。
移除集群
规则:不能移除登录节点,不能移除自己的master节点。可以删除其他的master或者slave节点
# 根据上面可以看出 1efc0139a5422c68f1c43428d1d6f566ce361fed 就是6378节点
127.0.0.1:6378> CLUSTER FORGET 1efc0139a5422c68f1c43428d1d6f566ce361fed
(error) ERR I tried hard but I can't forget myself...
# 登录6378的slave节点6391,删除6378,失败。
[root@VM_0_10_centos conf]# redis-cli -c -h 127.0.0.1 -p 6391 -a pjjlt1126
127.0.0.1:6391> CLUSTER FORGET 1efc0139a5422c68f1c43428d1d6f566ce361fed
(error) ERR Can't forget my master!
# 将刚加入的节点 6396
127.0.0.1:6378> CLUSTER FORGET f8c884f07375cb524236341c4fcb963f58f82622
OK
127.0.0.1:6378> CLUSTER NODES
114d082bb43c67042c806e0060f5fb8157736b98 127.0.0.1:6390@16390 slave ca998854f1d96e2b64b7304aea5e5b4c96a9d85a 0 1604675461284 5 connected
1efc0139a5422c68f1c43428d1d6f566ce361fed 127.0.0.1:6378@16378 myself,master - 0 1604675460000 1 connected 0-5460
2eefbdc56047282fc80baf3cc7bc08ff86dbdf9e 127.0.0.1:6395@16395 master - 0 1604675460283 7 connected
f10fc263b1b887fe175307b2fb7600370d39c0e1 127.0.0.1:6389@16389 master - 0 1604675462284 8 connected 5461-10922
e1eb98ead97d9b22fe4538601cbcd193e998baad 127.0.0.1:6380@16380 slave f10fc263b1b887fe175307b2fb7600370d39c0e1 0 1604675462000 8 connected
ca998854f1d96e2b64b7304aea5e5b4c96a9d85a 127.0.0.1:6381@16381 master - 0 1604675460000 3 connected 10923-16383
0f75c7f994a43551671e955a9f72c28a9c6edb56 127.0.0.1:6391@16391 slave 1efc0139a5422c68f1c43428d1d6f566ce361fed 0 1604675463287 6 connected
发现移除了,由于node.conf文件还存在(cluster-config-file
配置的那个文件),还可以恢复移除
# 恢复移除
127.0.0.1:6378> CLUSTER SAVECONFIG
OK
# 发现6396它又回来了
127.0.0.1:6378> CLUSTER NODES
114d082bb43c67042c806e0060f5fb8157736b98 127.0.0.1:6390@16390 slave ca998854f1d96e2b64b7304aea5e5b4c96a9d85a 0 1604675573000 5 connected
1efc0139a5422c68f1c43428d1d6f566ce361fed 127.0.0.1:6378@16378 myself,master - 0 1604675569000 1 connected 0-5460
2eefbdc56047282fc80baf3cc7bc08ff86dbdf9e 127.0.0.1:6395@16395 master - 0 1604675572000 7 connected
f10fc263b1b887fe175307b2fb7600370d39c0e1 127.0.0.1:6389@16389 master - 0 1604675572000 8 connected 5461-10922
e1eb98ead97d9b22fe4538601cbcd193e998baad 127.0.0.1:6380@16380 slave f10fc263b1b887fe175307b2fb7600370d39c0e1 0 1604675571000 8 connected
f8c884f07375cb524236341c4fcb963f58f82622 127.0.0.1:6396@16396 slave 2eefbdc56047282fc80baf3cc7bc08ff86dbdf9e 0 1604675572509 7 connected
ca998854f1d96e2b64b7304aea5e5b4c96a9d85a 127.0.0.1:6381@16381 master - 0 1604675574514 3 connected 10923-16383
0f75c7f994a43551671e955a9f72c28a9c6edb56 127.0.0.1:6391@16391 slave 1efc0139a5422c68f1c43428d1d6f566ce361fed 0 1604675573511 6 connected
模拟宕机
首先说一个坑:在cluster集群模式下,不能直接kill -9 某个节点,只能用kill(当然模拟宕机咱们用的是CLUSTER FORGET命令)。kill -9 ,再重启集群的时候会报错,需要删除pidfile、data、log等等一些东西,才能重启集群成功,所以尽量不要kill -9。
直接kill 6378 试试
[root@VM_0_10_centos conf]# redis-cli -c -h 127.0.0.1 -p 6391 -a 123456
127.0.0.1:6391> CLUSTER NODES
0f75c7f994a43551671e955a9f72c28a9c6edb56 127.0.0.1:6391@16391 myself,master - 0 1604675774000 9 connected 0-5460
ca998854f1d96e2b64b7304aea5e5b4c96a9d85a 127.0.0.1:6381@16381 master - 0 1604675779737 3 connected 10923-16383
f8c884f07375cb524236341c4fcb963f58f82622 127.0.0.1:6396@16396 slave 2eefbdc56047282fc80baf3cc7bc08ff86dbdf9e 0 1604675778000 7 connected
f10fc263b1b887fe175307b2fb7600370d39c0e1 127.0.0.1:6389@16389 master - 0 1604675777000 8 connected 5461-10922
2eefbdc56047282fc80baf3cc7bc08ff86dbdf9e 127.0.0.1:6395@16395 master - 0 1604675776000 7 connected
114d082bb43c67042c806e0060f5fb8157736b98 127.0.0.1:6390@16390 slave ca998854f1d96e2b64b7304aea5e5b4c96a9d85a 0 1604675779000 5 connected
1efc0139a5422c68f1c43428d1d6f566ce361fed 127.0.0.1:6378@16378 master,fail - 1604675757260 1604675756000 1 disconnected
e1eb98ead97d9b22fe4538601cbcd193e998baad 127.0.0.1:6380@16380 slave f10fc263b1b887fe175307b2fb7600370d39c0e1 0 1604675778000 8 connected
发现此时6378为master,fail
,而它原来的slave节点为master
。再重启6378节点看看。
[root@VM_0_10_centos conf]# redis-server redis-6378.conf
[root@VM_0_10_centos conf]# redis-cli -c -h 127.0.0.1 -p 6391 -a 123456
127.0.0.1:6391> CLUSTER NODES
0f75c7f994a43551671e955a9f72c28a9c6edb56 127.0.0.1:6391@16391 myself,master - 0 1604675996000 9 connected 0-5460
ca998854f1d96e2b64b7304aea5e5b4c96a9d85a 127.0.0.1:6381@16381 master - 0 1604675993000 3 connected 10923-16383
f8c884f07375cb524236341c4fcb963f58f82622 127.0.0.1:6396@16396 slave 2eefbdc56047282fc80baf3cc7bc08ff86dbdf9e 0 1604675992368 7 connected
f10fc263b1b887fe175307b2fb7600370d39c0e1 127.0.0.1:6389@16389 master - 0 1604675997000 8 connected 5461-10922
2eefbdc56047282fc80baf3cc7bc08ff86dbdf9e 127.0.0.1:6395@16395 master - 0 1604675996376 7 connected
114d082bb43c67042c806e0060f5fb8157736b98 127.0.0.1:6390@16390 slave ca998854f1d96e2b64b7304aea5e5b4c96a9d85a 0 1604675997376 5 connected
1efc0139a5422c68f1c43428d1d6f566ce361fed 127.0.0.1:6378@16378 slave 0f75c7f994a43551671e955a9f72c28a9c6edb56 0 1604675995000 9 connected
e1eb98ead97d9b22fe4538601cbcd193e998baad 127.0.0.1:6380@16380 slave f10fc263b1b887fe175307b2fb7600370d39c0e1 0 1604675998378 8 connected
发现此时原来的master
节点6378变成了6391的slave
节点了。
但是,只有当master节点有slot卡槽的时候,才会出现主从节点转化,当master节点没有卡槽时,不会进行转化。例如,删除6395,再重启,发现6395还是master
,6396还是slave
。
另外,上面提到的node.conf,不仅可以帮助移除恢复(CLUSTER SAVECONFIG),还可以记录刚刚的CLUSTER
指令日志。
以上,就是cluster模式
的搭建介绍,谢谢观看。