直接上硬货
主从复制原理
①:从服务器slave先于主服务器master建立socket长连接
②:从服务器slave向主服务器master发送一个PSYNC命令,请求复制数据。
③:主服务器master接收到PSYNC命令后,会通过bgsave命令利用子线程生成最新的rdb快照文件,并发送给从服务器slave。
持久化期间,master会继续接收客户端的请求,它会把这些可能修改数据集的请求缓存在内存repl buffer中
④:slave清掉无用数据,并接受master传来的数据加载到内存中
⑤:master再将之前持久化时缓存在内存中的命令发送给slave。
⑥:slave接受master发过来的新命令并执行
⑦:此时数据已同步完毕,当master再有新的写操作,会通过socket长连接持续的发给slave,保证主从数据一致性!
注意: 如果master收到了多个slave并发连接请求,它只会进行一次持久化,而不是一个连接一次,
然后再把这一份持久化的数据发送给多个并发连接的slave。
如果在主从传输过程中,从节点挂了怎么办?
当salve因为网络等原因接收到一半数据时挂掉了,经过一段时间后,人为的重启了salve从节点,那么此时的数据传输是怎么处理呢?
答:从redis2.8版本开始,redis改用可以支持部分数据复制的命令PSYNC去master同步数据,slave与master能够在网络连接断开重连后只进行部分数据复制(断点续传)。流程图如下:
①:首先redis在运行时会默认开启一个缓存池,用于缓存最近的redis命令,可以在6379.conf中配置
repl-backlog-size 1mb ####redis命令缓存池,默认大小为1Mb
②:当slave与master断开并重新建立连接时,slave会向master发送PSYNC命令,并通过offset偏移量定位到断开连接时传输数据的位置,从这个位置开始进行断点续传
③:如果slave节点断开时间太久,导致偏移量太旧,已经在master中的命令缓存池中找不到对应的位置,那么就会进行一次全量数据的复制。无法使用断点续传了!
什么是主从复制风暴?
主从复制风暴:多个从节点同时复制主节点导致主节点压力过大
为了解决主从复制风暴问题,可以让部分从节点与从节点同步数据,架构如下设计:
主从复制优缺点
优点:
主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式 |
---|
当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复 |
在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务,分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量 |
高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础 |
缺点:
故障恢复无法自动化;写操作无法负载均衡;存储能力受到单机的限制。 |
---|
每次slaveof断开后,(无论是主动断开,还是网络故障),再连接master;都要master全部dump出来rdb,再aof,即同步的过程都要重新执行1遍。 |
所以不要多台slaveof同时启动,否则master可能IO剧增。 |
redis主从复制
1.底层环境
主master | 20.0.0.21 |
---|---|
从slave | 20.0.0.22,20.0.0.23 |
系统 | Centos7.4 |
其他 | 网关:20.0.0.2,防火墙核心防护全关 |
2.实验拓扑图
3.所有服务器安装redis
#############安装redis########
###上传5.0版本包源到opt下
[root@localhost ~]# cd /opt/
[root@localhost opt]# ls
redis-5.0.7.tar.gz rh
[root@localhost opt]# tar zxvf redis-5.0.7.tar.gz
[root@localhost opt]# yum -y install gcc gcc-c++ make
[root@localhost opt]# cd redis-5.0.7/
[root@localhost redis-5.0.7]# make
###因为5.0版本所有路径都是默认安装的,所以我们直接make就可以了
[root@localhost redis-5.0.7]# make install
[root@localhost redis-5.0.7]# cd utils/
###启动自动安装脚本,一路回车即可################
[root@localhost utils]# ./install_server.sh
Welcome to the redis service installer
This script will help you easily set up a running redis server
Please select the redis port for this instance: [6379]
Selecting default: 6379
Please select the redis config file name [/etc/redis/6379.conf]
Selected default - /etc/redis/6379.conf
Please select the redis log file name [/var/log/redis_6379.log]
Selected default - /var/log/redis_6379.log
Please select the data directory for this instance [/var/lib/redis/6379]
Selected default - /var/lib/redis/6379
Please select the redis executable path [/usr/local/bin/redis-server]
Selected config:
Port : 6379
Config file : /etc/redis/6379.conf
Log file : /var/log/redis_6379.log
Data dir : /var/lib/redis/6379
Executable : /usr/local/bin/redis-server
Cli Executable : /usr/local/bin/redis-cli
Is this ok? Then press ENTER to go on or Ctrl-C to abort.
Installing service...
Successfully added to chkconfig!
Successfully added to runlevels 345!
Starting Redis server...
Installation successful!
4.修改配置文件
[root@localhost utils]# vim /etc/redis/6379.conf
######所有服务器修改配置文件##############
daemonize yes #后台启动
70 #bind 127.0.0.1 ##不注释也可以,在后面加本机IP。注释掉默认监听所有网卡IP
89 protected-mode no ##保护模式,开启后相当于单机模式,无法主从同步
137 daemonize yes ###以独立进程启动,默认是开启的
##主服务器开启缓存池###
414 repl-backlog-size 1mb #redis命令缓存池,默认大小为1Mb,根据生产环境自行调整
###接下来在两台从服务器开启复制功能####
287 replicaof 20.0.0.21 6379 ###复制20.0.0.21的数据,从6379端口
325 replica-read-only yes ###配置从节点只读,一定要设置,默认是开启的
5.验证主从复制
###验证主从复制####,master上写入数据,两台从服务器查看是否有数据###
[root@master utils]# redis-cli -h 20.0.0.21 -p 6379
20.0.0.21:6379> set name zhangsan
OK
20.0.0.21:6379> get name
"zhangsan"
20.0.0.21:6379> quit
##从:20.0.0.22
[root@slave1 utils]# redis-cli -h 20.0.0.22
20.0.0.22:6379> get name
"zhangsan"
##从:20.0.0.23
[root@slave2 utils]# redis-cli -h 20.0.0.23 -p 6379
20.0.0.23:6379> get name
"zhangsan"
###实验配置完成
生产环境下快速恢复master
将20.0.0.22设置成主,将20.0.0.23服务器的redis配置文件改成同步20.0.0.22
哨兵模式原理
-
sentinel哨兵是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点的状态!
-
哨兵架构下client端第一次请求redis服务时,会先从哨兵找出redis的主节点,后续就直接访问redis的主节点,不会每次都通过sentinel代理访问redis的主节点,当redis的主节点发生变化,哨兵会第一时间感知到,并且将新的redis主节点通知给client端(这里面redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息)
哨兵的主要作用
现象:
- 当master节点挂掉后,服务端控制台会打印 连接超时错误,当过一段时间后,又恢复正常,可以继续向redis中写入数据!
原因:
-
原因就是哨兵会时刻监视着master节点,当master节点挂掉,此时服务端控制台会打印连接超时错误。但同时哨兵经过半数机制确认master挂掉,会选举出一个slave作为新的master
-
选举的这顿时间内,控制台还是会打印错误,一旦选举成功,就会恢复正常连接,这也是出现以上现象的原因!!
-
当原来挂掉的master节点重新恢复时,将自动称为新的master的丛节点,完成哨兵高可用架构!
哨兵要设为奇数,最少三台,里面涉及到投票问题!!
配置哨兵模式
1.底层环境
sentinels1 | 20.0.0.24 |
---|---|
sentinels2 | 20.0.0.25 |
sentinels3 | 20.0.0.26 |
系统 | Centos7.4 |
其他 | 网关:20.0.0.2,防火墙核心防护全关 |
2.首先安装redis
##首先安装redis,安装过程看上面###下面是shell脚本自动安装,将包拖到/opt下自动完成##
[root@local opt]# vim redis.sh
#!/bin/bash
cd /opt
yum -y install gcc-c++ gcc make
tar zxvf redis-5.0.7.tar.gz
cd redis-5.0.7/
make
make install
cd utils/
echo -e "\n\n\n\n\n\n" | ./install_server.sh
cp -p /etc/init.d/redis_6379 /etc/init.d/redis_6379bak
mv /etc/init.d/redis_6379 /etc/init.d/redis
sed -i '2a#chkconfig: 2345 90 25' /etc/init.d/redis
chkconfig --add redis
[root@local opt]# chmod +x redis.sh
[root@local opt]# ./redis.sh
3.修改配置文件
####以下命令三台哨兵服务器都需要完成#####
[root@localhost opt]# cd /opt/redis-5.0.7/
[root@localhost redis-5.0.7]# cp -p sentinel.conf /etc/redis/
[root@localhost redis-5.0.7]# cd /etc/redis/
[root@localhost redis]# ls
6379.conf sentinel.conf
[root@localhost redis]# vim sentinel.conf
21 port 26379 ###监听端口
26 daemonize yes ###以独立的进程开启
31 pidfile /var/run/redis-sentinel.pid ###PID文件位置+文件名
36 logfile "26379.log" ###日志文件名
65 dir /var/log ###工作目录,最好新创建一个空目录给它
84 sentinel monitor mymaster 20.0.0.21 6379 2 ###监听master的地址
###重启redis#####
[root@localhost redis]# /etc/init.d/redis restart
4.开启哨兵模式
#######开启哨兵模式,因为哨兵主要靠配置文件,所以一定要告知用哪一个配置文件######
[root@localhost redis]# /opt/redis-5.0.7/src/redis-sentinel /etc/redis/sentinel.conf
6394:X 07 Nov 2020 16:06:06.673 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
6394:X 07 Nov 2020 16:06:06.673 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=6394, just started
6394:X 07 Nov 2020 16:06:06.673 # Configuration loaded
###查看哨兵的info消息###
[root@localhost redis]# redis-cli -p 26379
127.0.0.1:26379> info
##最后一行##,因为之添加了一台,所以sentinels=1,另外两台添加完后是sentinels=3
master0:name=mymaster,status=sdown,address=20.0.0.21:6379,slaves=2,sentinels=1
###全部哨兵配置完成后,可以查看哨兵的配置文件,在最后会自动生成以下信息######
[root@localhost redis]# vim sentinel.conf
protected-mode no
sentinel known-replica mymaster 20.0.0.23 6379
sentinel known-replica mymaster 20.0.0.22 6379
sentinel known-sentinel mymaster 20.0.0.24 26379 e52a4a4f9242a6232a53ea22615d10949b7a38a2
sentinel known-sentinel mymaster 20.0.0.25 26379 81e85a0dc0afd72a7cdad569641f4a742b1a69b5
sentinel current-epoch 0
5.验证哨兵模式
-------------------4.1 关闭master服务器,模拟故障 -------------------
[root@localhost ~]# redis-cli
20.0.0.21:6379> shutdown ##关闭master
进入哨兵客户端查看主从信息
[root@localhost ~]# redis-cli -p 26379
20.0.0.24:26379> info
master0:name=mymaster,status=ok,address=20.0.0.22:6379,slaves=2,sentinels=3
##已经完成了故障转换,主服务器master变为20.0.0.22(原为20.0.0.21)
########在新master上写入数据测试#########
[root@localhost ~]# redis-cli -h 20.0.0.22
20.0.0.22:6379> set score 89 ##可以写入数据,已经不是slave的只读状态了
OK
20.0.0.22:6379> get score
"89"
###########在另一台仅存的slave上测试主从##############
[root@localhost ~]# redis-cli -h 20.0.0.23
20.0.0.23:6379> keys * ##可以查看的新master上插入的键值,确认主从故障切换成功
1) "score"
2) "name"
20.0.0.23:6379> get score
"89"
#######查看哨兵节点配置文件末尾信息############
[root@localhost ~]# vim /etc/redis/sentinel.conf
protected-mode no
sentinel known-replica mymaster 20.0.0.23 6379
sentinel known-replica mymaster 20.0.0.21 6379
##配置文件自动修改,将192.168.10.10(原master)降级为slave
sentinel known-sentinel mymaster 20.0.0.24 26379 0cca768420585707028ca7371c266472692dcac8
sentinel known-sentinel mymaster 20.0.0.25 26379 8322b2583d5af36eeb93ae3a810c6ec7846037fd
sentinel current-epoch 1
####重新开启原master(20.0.0.21)进行主从复制验证 #########
[root@localhost ~]# service redis start
Starting Redis server...
[root@localhost ~]# redis-cli -h 20.0.0.21
20.0.0.21:6379> keys * ## 宕机间在新master上写入的数据也被同步过来了
1) "name"
2) "score"
20.0.0.21:6379> get score
"89"
20.0.0.21:6379> set ABC 123 ## 再次开启后不会切换回master,不再具有写的权限
(error) READONLY You can't write against a read only replica.