通过持久化功能,Redis保证了即使在服务器重启的情况下也不会损失(或少量损失)数据,因为持久化会把内存中数据保存到硬盘上,重启会从硬盘上加载数据。
但是由于数据是存储在一台服务器上的,如果这台服务器出现硬盘故障等问题,也会导致数据丢失。为了避免单点故障,通常的做法是将数据库复制多个副本以部署在不同的服务器上,这样即使有一台服务器出现故障,其他服务器依然可以继续提供服务。为此, Redis 提供了复制(replication)功能,可以实现当一台数据库中的数据更新后,自动将更新的数据同步到其他数据库上。
在复制的概念中,数据库分为两类,一类是主数据库(master),另一类是从数据库(slave)。主数据库可以进行读写操作,当写操作导致数据变化时会自动将数据同步给从数据库。而从数据库一般是只读的,并接受主数据库同步过来的数据。一个主数据库可以拥有多个从数据库,而一个从数据库只能拥有一个主数据库
故障无法自动化,主节点宕机从节点无法自动顶上去成为主节点
当主数据库遇到异常中断服务后,开发者可以通过手动的方式选择一个从数据库来升格为主数据库,以使得系统能够继续提供服务。然而整个过程相对麻烦且需要人工介入,难以实现自动化。 为此,Redis 2.8中提供了哨兵工具来实现自动化的系统监控和故障恢复功能。
哨兵的作用就是监控redis主、从数据库是否正常运行,主出现故障自动将从数据库转换为主数据库。
解决了故障自动化,(哨兵会监控主节点,一旦发现主节点宕掉,会在从节点上选出一台成为主节点,整个过程自动化),但是在故障转移期间导致不可用
使用集群,只需要将每个数据库节点的cluster-enable配置打开即可。每个集群中至少需要三个主数据库才能正常运行。
即使使用哨兵,redis每个实例也是全量存储,每个redis存储的内容都是完整的数据,浪费内存且有木桶效应。为了最大化利用内存,可以采用集群,就是分布式存储。即每台redis存储不同的内容。
集群至少需要3主3从,且每个实例使用不同的配置文件,主从不用配置,集群会自己选。
通过集群redis解决了写操作无法负载均衡,以及存储能力受到单机限制的问题,较为完善。
本次将介绍集群模式,主从和哨兵模式请看我其他的两篇文章
环境说明:
准备3台服务器,每台服务器运行两个Redis
主机说明 | 主机IP | 端口 |
---|---|---|
Redis | 192.168.100.100 | 7000 7001 |
Redis | 192.168.100.200 | 7002 7003 |
Redis | 192.168.100.250 | 7004 7005 |
100:
[root@100 redis-5.0.5]# vim redis-7000.conf
daemonize yes
port 7000
logfile 7000.log
dir ./
bind 192.168.100.100 127.0.0.1
cluster-enabled yes
cluster-config-file nodes_7000.conf
cluster-node-timeout 15000
appendonly yes
appendfilename aof-7000.aof
appendfsync everysec
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
[root@100 redis-5.0.5]# vim redis-7001.conf
daemonize yes
port 7001
logfile 7001.log
dir ./
bind 192.168.100.100 127.0.0.1
cluster-enabled yes
cluster-config-file nodes_7001.conf
cluster-node-timeout 15000
appendonly yes
appendfilename aof-7001.aof
appendfsync everysec
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 其他两台服务器的配置一样的需要改一下 prot,logfile,bind(改为本机就可),cluster-config-file,aof
配置好之后就可以启动了
100:
[root@100 redis-5.0.5]# ./src/redis-server redis-7000.conf
[root@100 redis-5.0.5]# ./src/redis-server redis-7001.conf
[root@100 redis-5.0.5]# netstat -tunlp |grep redis
tcp 0 0 127.0.0.1:17000 0.0.0.0:* LISTEN 23385/./src/redis-s
tcp 0 0 192.168.100.100:17000 0.0.0.0:* LISTEN 23385/./src/redis-s
tcp 0 0 127.0.0.1:17001 0.0.0.0:* LISTEN 23390/./src/redis-s
tcp 0 0 192.168.100.100:17001 0.0.0.0:* LISTEN 23390/./src/redis-s
tcp 0 0 127.0.0.1:7000 0.0.0.0:* LISTEN 23385/./src/redis-s
tcp 0 0 192.168.100.100:7000 0.0.0.0:* LISTEN 23385/./src/redis-s
tcp 0 0 127.0.0.1:7001 0.0.0.0:* LISTEN 23390/./src/redis-s
tcp 0 0 192.168.100.100:7001 0.0.0.0:* LISTEN 23390/./src/redis-s
200:
[root@100 redis-5.0.5]# ./src/redis-server redis-7002.conf
[root@100 redis-5.0.5]# ./src/redis-server redis-7003.conf
250:
[root@100 redis-5.0.5]# ./src/redis-server redis-7004.conf
[root@100 redis-5.0.5]# ./src/redis-server redis-7005.conf
[root@100 redis-5.0.5]# systemctl stop firewalld
[root@100 redis-5.0.5]# setenforce 0
[root@100 redis-5.0.5]# ./src/redis-cli --cluster create 192.168.100.100:7000 192.168.100.100:7001 192.168.100.200:7002 192.168.100.200:7003 192.168.100.250:7004 192.168.100.250:7005 --cluster-replicas 1
## cluster-replicas 1 代表 一个master后有几个slave,1代表为1个slave节点
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.100.200:7003 to 192.168.100.100:7000 # 发现7000 7002 7004自动成为master
Adding replica 192.168.100.250:7005 to 192.168.100.200:7002
Adding replica 192.168.100.100:7001 to 192.168.100.250:7004
...
100:
[root@100 redis-5.0.5]# ./src/redis-cli -c -p 7000 # -c 代表参数连接到集群中
127.0.0.1:7000> CLUSTER NODES
dbdc7dd01b4ccd7ee4be7072004c972bfb05c496 192.168.100.250:7005@17005 slave 2d11224f74b0f16dc8acb92733081d38a3f44f2a 0 1592969036418 6 connected
2d11224f74b0f16dc8acb92733081d38a3f44f2a 192.168.100.200:7002@17002 master - 0 1592969033000 3 connected 5461-10922
059f1b750068453f57ec911922382e78c669a3cb 192.168.100.100:7000@17000 myself,master - 0 1592969034000 1 connected 0-5460
3f4b5ab4e13cd1f5ec7b7317b4222e68ae50f908 192.168.100.100:7001@17001 slave 31fa28c14f25af7bb09445f170c7f1ea94044747 0 1592969035000 5 connected
841a603d75ac2c0172c818094da82629b270fbf8 192.168.100.200:7003@17003 slave 059f1b750068453f57ec911922382e78c669a3cb 0 1592969035000 4 connected
31fa28c14f25af7bb09445f170c7f1ea94044747 192.168.100.250:7004@17004 master - 0 1592969035410 5 connected 10923-16383
127.0.0.1:7000>
# 可以找到对应的ID确定主从节点关系
master slave
7002 7005
7000 7003
7004 7001
[root@100 redis-5.0.5]# ./src/redis-cli -c -p 7000
127.0.0.1:7000> set aaa bbb
-> Redirected to slot [10439] located at 192.168.100.200:7002
OK
192.168.100.200:7002> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.100.250,port=7005,state=online,offset=45072,lag=1 #可以看到7005位7002的salve
master_replid:b5b46eea2bce27158fc12f79c58b0dc305b37b57
master_replid2:0000000000000000000000000000000000000000
...
[root@250 redis-5.0.5]# redis-cli -c -p 7005
127.0.0.1:7005> get aaa
-> Redirected to slot [10439] located at 192.168.100.200:7002
"bbb"
192.168.100.200:7002>
[root@100 redis-5.0.5]# ./src/redis-cli -c -p 7000
127.0.0.1:7000> set bbb ccc
OK
127.0.0.1:7000> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.100.200,port=7003,state=online,offset=45607,lag=0 #slave为7003
master_replid:c7bb2c36e96d91722ad23cc7c53abc7aa8c69b57
...
[root@200 redis-5.0.5]# redis-cli -c -p 7003
127.0.0.1:7003> get bbb
-> Redirected to slot [5287] located at 192.168.100.100:7000
"ccc"
192.168.100.100:7000>
我们从上面可以看出7002为master,7005为其从节点,我们先停掉7002看7005是否会成为master
[root@200 redis-5.0.5]# ps -ef|grep redis
root 24228 1 0 06:33 ? 00:01:01 ./src/redis-server 192.168.100.200:7002 [cluster]
root 24233 1 0 06:33 ? 00:01:02 ./src/redis-server 192.168.100.200:7003 [cluster]
root 25462 25061 0 15:53 pts/1 00:00:00 grep --color=auto redis
[root@200 redis-5.0.5]# kill 24228
[root@250 redis-5.0.5]# redis-cli -c -p 7005
127.0.0.1:7005> info replication
# Replication
role:master ## 发现7005已经自动成为了master
connected_slaves:0
master_replid:713157092ddc0dfbf1b64e6b2776484b88cd94ec
master_replid2:b5b46eea2bce27158fc12f79c58b0dc305b37b57
...
127.0.0.1:7005>
## 重新启动7002
[root@200 redis-5.0.5]# ./src/redis-server redis-7002.conf
[root@200 redis-5.0.5]# redis-cli -c -p 7002
127.0.0.1:7002> info replication
# Replication
role:slave ## 发现重新启动后成为了7005的slave
master_host:192.168.100.250
master_port:7005
master_link_status:up
...
127.0.0.1:7002>
#添加节点7006和7007
#在100这台服务器上新增两个配置文件,修改一下端口就可以,其他配置一样
/usr/local/etc/redis-5.0.5/redis-7006.conf
/usr/local/etc/redis-5.0.5/redis-7006.conf
[root@100 redis-5.0.5]# ./src/redis-server redis-7006.conf
[root@100 redis-5.0.5]# ./src/redis-server redis-7007.conf
#默认添加为master
[root@100 redis-5.0.5]# ./src/redis-cli --cluster add-node 192.168.100.100:7006 192.168.100.100:7000
[root@100 redis-5.0.5]# ./src/redis-cli --cluster add-node 192.168.100.100:7007 192.168.100.100:7000
[root@100 redis-5.0.5]# redis-cli -p 7000
127.0.0.1:7000> CLUSTER NODES
dbdc7dd01b4ccd7ee4be7072004c972bfb05c496 192.168.100.250:7005@17005 master - 0 1592990967560 7 connected 5461-10922
d7cff216fa0e5f5b9edb63991a359b44a663826b 192.168.100.100:7006@17006 master - 0 1592990969000 0 connected
2d11224f74b0f16dc8acb92733081d38a3f44f2a 192.168.100.200:7002@17002 slave dbdc7dd01b4ccd7ee4be7072004c972bfb05c496 0 1592990965000 7 connected
059f1b750068453f57ec911922382e78c669a3cb 192.168.100.100:7000@17000 myself,master - 0 1592990966000 1 connected 0-5460
3f4b5ab4e13cd1f5ec7b7317b4222e68ae50f908 192.168.100.100:7001@17001 slave 31fa28c14f25af7bb09445f170c7f1ea94044747 0 1592990968566 5 connected
841a603d75ac2c0172c818094da82629b270fbf8 192.168.100.200:7003@17003 slave 059f1b750068453f57ec911922382e78c669a3cb 0 1592990969574 4 connected
9d40d2dd908ebe360037fff34c4bdfb4bdc9b073 192.168.100.100:7007@17007 master - 0 1592990966554 8 connected
31fa28c14f25af7bb09445f170c7f1ea94044747 192.168.100.250:7004@17004 master - 0 1592990970579 5 connected 10923-16383
# 删除节点7007
[root@100 redis-5.0.5]# redis-cli --cluster del-node 192.168.100.100:7007 9d40d2dd908ebe360037fff34c4bdfb4bdc9b073 #NODES ID
# 通过cluster nodes可以查看7007节点是否删除
127.0.0.1:7000> CLUSTER NODES
dbdc7dd01b4ccd7ee4be7072004c972bfb05c496 192.168.100.250:7005@17005 master - 0 1592991278000 7 connected 5461-10922
d7cff216fa0e5f5b9edb63991a359b44a663826b 192.168.100.100:7006@17006 master - 0 1592991278816 0 connected
2d11224f74b0f16dc8acb92733081d38a3f44f2a 192.168.100.200:7002@17002 slave dbdc7dd01b4ccd7ee4be7072004c972bfb05c496 0 1592991279822 7 connected
059f1b750068453f57ec911922382e78c669a3cb 192.168.100.100:7000@17000 myself,master - 0 1592991276000 1 connected 0-5460
3f4b5ab4e13cd1f5ec7b7317b4222e68ae50f908 192.168.100.100:7001@17001 slave 31fa28c14f25af7bb09445f170c7f1ea94044747 0 1592991280833 5 connected
841a603d75ac2c0172c818094da82629b270fbf8 192.168.100.200:7003@17003 slave 059f1b750068453f57ec911922382e78c669a3cb 0 1592991278000 4 connected
31fa28c14f25af7bb09445f170c7f1ea94044747 192.168.100.250:7004@17004 master - 0 1592991279000 5 connected 10923-16383
127.0.0.1:7000>
# 新增从节点
# 新增7007为7006的从节点
[root@100 redis-5.0.5]# redis-cli --cluster add-node 192.168.100.100:7007 192.168.100.100:7006 --cluster-slave --cluster-master-id d7cff216fa0e5f5b9edb63991a359b44a663826b
[root@100 redis-5.0.5]# ./src/redis-cli -p 7007
127.0.0.1:7007> info replication
# Replication
role:slave
master_host:192.168.100.100
master_port:7006
master_link_status:up
master_last_io_seconds_ago:4
master_sync_in_progress:0
...
127.0.0.1:7007>
# 如果遇到这种报错是因为集群已经形成了配置文件,删掉重新启动一下再次添加
[ERR] Node 192.168.100.100:7007 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.