Redis高可用群集——主从复制+哨兵模式

一、Redis主从复制

1.为什么要主从复制

  • 单机的 redis,能够承载的 QPS 大概就在上万到几万不等。
  • 对于缓存来说,一般都是用来支撑读高并发的。
  • 因此架构做成主从(master-slave)架构,一主多从,主负责写,并且将数据复制到其它的 slave 节点,从节点负责读。所有的读请求全部走从节点。这样也可以很轻松实现水平扩容,支撑读高并发。

redis replication -> 主从架构 -> 读写分离 -> 水平扩容支撑读高并发

2.Redis主从复制的特点

redis 采用异步方式复制数据到 slave 节点,不过 redis2.8 开始,slave node 会周期性地确认自己每次复制的数据量;

  • 一个 master node 是可以配置多个 slave node 的;
  • slave node 也可以连接其他的 slave node;
  • slave node 做复制的时候,不会 block master node 的正常工作;
  • slave node 在做复制的时候,也不会 block 对自己的查询操作,它会用旧的数据集来提供服务;但是复制完成的时候,需要删除旧数据集,加载新数据集,这个时候就会暂停对外服务了;
  • slave node 主要用来进行横向扩容,做读写分离,扩容的 slave node 可以提高读的吞吐量。

注意点:
1. 如果采用了主从架构,那么建议必须开启 master 的持久化,不建议用 slave 作为 master 的数据热备。因为如果你关掉 master 的持久化,可能在 master 出现故障宕机重启的时候数据是被清空的,然后可能一经过复制, slave node 的数据也丢了。
2. 此外,master 的各种备份方案,也需要做。万一本地的所有文件丢失了,从备份中挑选一份 rdb 去恢复 master,这样才能确保启动的时候,是有数据的,即使采用了高可用机制,slave node 可以自动接管 master node,但也可能 sentinel 还没检测到 master failure,master node 就自动重启了,还是可能导致上面所有的 slave node 数据被清空。

3.Redis 主从复制的核心原理

  1. 当启动一个 slave node 的时候,它会发送一个 PSYNC 命令给 master node。
  2. 如果这是 slave node 初次连接到 master node,那么会触发一次 full resynchronization 全量复制。
  3. 此时 master 会启动一个后台线程,开始在生成一份 RDB 快照文件,同时还会将从客户端 client 新收到的所有写命令缓存在内存中。
  4. RDB 文件生成完毕后, master 会将这个 RDB 发送给 slave,slave 会先写入本地磁盘,然后再从本地磁盘加载到内存中,接着 master 会将内存中缓存的写命令发送到 slave,slave 也会同步这些数据。
  5. slave node 如果跟 master node 有网络故障,断开了连接,会自动重连,连接之后 master node 仅会复制给 slave 部分缺少的数据。

Redis高可用群集——主从复制+哨兵模式_第1张图片
Redis高可用群集——主从复制+哨兵模式_第2张图片

4.主从复制的断点续传

  • 从 redis2.8 开始,就支持主从复制的断点续传,如果主从复制过程中,网络连接断掉了,那么可以接着上次复制的地方,继续复制下去,而不是从头开始复制一份。

  • master node 会在内存中维护一个 backlog,master 和 slave 都会保存一个 replica offset 还有一个 master run id,offset 就是保存在 backlog 中的。如果 master 和 slave 网络连接断掉了,slave 会让 master 从上次 replica offset 开始继续复制,如果没有找到对应的 offset,那么就会执行一次 resynchronization。

  • 如果根据 host+ip 定位 master node,是不靠谱的,如果 master node 重启或者数据出现了变化,那么 slave node 应该根据不同的 run id 区分。

  • 无磁盘化复制:master 在内存中直接创建 RDB,然后发送给 slave,不会在自己本地落地磁盘了。只需要在配置文件中开启 repl-diskless-sync yes 即可。

  • 过期 key 处理:slave 不会过期 key,只会等待 master 过期 key。如果 master 过期了一个 key,或者通过 LRU 淘汰了一个 key,那么会模拟一条 del 命令发送给 slave。

二、Redis主从复制步骤

实验拓扑

Redis高可用群集——主从复制+哨兵模式_第3张图片

1.安装Redis(三台服务器都安装)

鉴于之前做过安装讲解,这里就直接脚本运行了

[root@localhost ~]# vi redis.sh
#!/bin/bash
##判断网络环境
ping www.baidu.com -c 3 -i 0.2

if [[ $? = 0 ]]
  then
    echo "网络正常"
 else 
    echo "网络异常,请检查网络"
fi
wget https://download.redis.io/releases/redis-5.0.10.tar.gz  
##安装编译环境
yum -y install gcc-c++ gcc make
tar zxvf redis-5.0.10.tar.gz -C /opt
cd /opt/redis-5.0.10/
make
make PREFIX=/usr/local/redis install
##执行配置脚本
cd /opt/redis-5.0.10/
cd utils/
echo -e "\n\n\n\n\/usr\/local\/redis\/bin\/redis-server\n\n" | ./install_server.sh 
ln -s /usr/local/redis/bin/* /usr/local/bin/
##备份配置文件
cp -p /etc/init.d/redis_6379 /etc/init.d/redis_6379bak
## service管理服务
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@localhost ~]# chmod +x redis
[root@localhost ~]# ./redis.sh

2.修改master的配置文件

[root@localhost ~]# vim /etc/redis/6379.conf
# bind 127.0.0.1     //70行,注释掉bind监听地址,注释后默认监听所有
protected-mode no    //80行,yes改为no,关闭保护模式,在保护模式下会拒绝所有外来请求
repl-backlog-size 1mb    //414行,设置backlog的大小
##backlog是一个缓冲区,在slave端失连时存放要同步到slave的数据,因此当一个slave要重连时,经常是不需要完全同步的,执行局部同步就足够了。backlog设置的越大,slave可以失连的时间就越长。但是会占用内存空间,因此根据实际工作环境需要进行修改
[root@localhost ~]# service redis restart  ##重启生效
Stopping ...
Redis stopped
Starting Redis server...

3.修改两台slave配置

[root@localhost ~]# vi /etc/redis/6379.conf
# bind 127.0.0.1     //70行,注释掉bind监听地址,注释后默认监听所有
protected-mode no    //80行,yes改为no,关闭保护模式,在保护模式下会拒绝所有外来请求
replicaof 192.168.10.10 6379     //287行,配置slave数据同步源(即master)的 ip  端口号
replica-read-only yes       //325行,开启slave的只读功能,默认开启
[root@localhost ~]# scp -p /etc/redis/6379.conf root@192.168.10.30:/etc/redis/6379.conf   ##因为两台slave的配置相同,因此可以通过scp的方式将这台redis的配置发送过去,重启服务
[root@localhost ~]# service redis restart
Stopping ...
Waiting for Redis to shutdown ...
Redis stopped
Starting Redis server...

4.验证主从

4.1 master 写入数据

[root@localhost ~]# redis-cli -h 192.168.10.10    ##登入主服务器master
192.168.10.10:6379> 
192.168.10.10:6379> set name zhangsan    ##写入数据
OK
192.168.10.10:6379> get name
"zhangsan"

4.2 slave 查看验证

[root@localhost ~]# redis-cli -h 192.168.10.20   ##salve1 查看数据,同步成功
192.168.10.20:6379> keys *
1) "name"
192.168.10.20:6379> get name
"zhangsan"
192.168.10.20:6379> 

[root@localhost ~]# redis-cli -h 192.168.10.30    ##slave2 查看数据 ,同步成功
192.168.10.30:6379> keys *
1) "name"
192.168.10.30:6379> get name
"zhangsan"
192.168.10.30:6379> 

三、Redis哨兵模式

1.哨兵模式功能介绍

  • 集群监控:负责监控 redis master 和 slave 进程是否正常工作。
  • 消息通知:如果某个 redis 实例有故障,那么哨兵负责发送消息作为报警通知给管理员。
  • 故障转移:如果 master node 挂掉了,会自动转移到 slave node 上。
  • 配置中心:如果故障转移发生了,通知 client 客户端新的 master 地址。

注意点:哨兵用于实现 redis 集群的高可用,本身也是分布式的,作为一个哨兵集群去运行,互相协同工作。

  1. 故障转移时,判断一个 master node 是否宕机了,需要大部分的哨兵都同意才行,涉及到了分布式选举的问题。
  2. 即使部分哨兵节点挂掉了,哨兵集群还是能正常工作的,因为如果一个作为高可用机制重要组成部分的故障转移系统本身是单点的,那就构不成高可用的群集了。

2.哨兵的核心知识

  1. 哨兵至少需要 3 个实例,来保证自己的健壮性。
  2. 哨兵 + redis 主从的部署架构,是不保证数据零丢失的,只能保证 redis 集群的高可用性。
  3. 对于哨兵 + redis 主从这种复杂的部署架构,尽量在测试环境和生产环境,都进行充足的测试和演练。
  4. 哨兵集群必须部署 2 个以上节点,如果哨兵集群仅仅部署了 2 个哨兵实例,quorum = 1(表示只要有一台哨兵节点判断master故障,就立即执行故障转移);一般情况下数三台哨兵节点构成群集,quorun=2(表示2个以上的哨兵节点判断master故障,则进行故障转移)。

3.redis 哨兵主备切换的数据丢失问题

在进行主备切换的时候,会有两种导致数据丢失的情况:

  1. 异步复制导致的数据丢失
    ◆ 因为 master->slave 的复制是异步的,所以可能有部分数据还没复制到 slave,master 就宕机了,此时这部分数据就丢失了。(主从复制通过RDB持久化的方式同步,类似于定时同步,每次同步都会有时间间隔,因此是异步的)
  2. 脑裂导致的数据丢失
    ◆ 脑裂,也就是说,某个 master 所在机器突然脱离了正常的网络,跟其他 slave 机器不能连接,但是实际上 master 还运行着。此时哨兵可能就会认为 master 宕机了,然后开启选举,将其他 slave 切换成了 master。这个时候,集群里就会有两个 master ,也就是所谓的脑裂。
    ◆ 此时虽然某个 slave 被切换成了 master,但是可能 client 还没来得及切换到新的 master,还继续向旧 master 写数据。因此旧 master 再次恢复的时候,会被作为一个 slave 挂到新的 master 上去,自己的数据会清空,重新从新的 master 复制数据。而新的 master 并没有后来 client 写入的数据,因此,这部分数据也就丢失了。

4.数据丢失问题的优化方案

在配置文件中修改如下两条配置

[root@localhost ~]# vi /etc/redis/6379.conf
min-slaves-to-write 1    ##最小slave数为1,表示至少有1台slave
min-slaves-max-lag 10    ##数据复制和同步的延迟不能超过 10 
  • RDB异步复制会因为写入次数低而造成同步将长的可能,设置同步时间最多不能超过10秒能尽可能的复制保留master上的数据
  • 网络不稳定的情况下,slave无法从master那同步数据,设置了最短时间后,最多只丢失10秒的数据,能尽可能的挽回损失。

四、主从复制+哨兵模式高可用群集部署

多少情况下 哨兵+主从构 成高可用群集,基于上面的主从部署,我们在添加哨兵群集,实现高可用

实验拓扑

Redis高可用群集——主从复制+哨兵模式_第4张图片

1.配置哨兵(三个节点都配置)

[root@localhost ~]# find / -name sentinel.conf   ##哨兵模式有个模板配置文件,在编译安装的源码目录下
/opt/redis-5.0.10/sentinel.conf
[root@localhost ~]# cp -p /opt/redis-5.0.10/sentinel.conf /etc/redis/   ##将其拷贝到/etc/redis目录下
[root@localhost ~]# cd /etc/redis/
[root@localhost redis]# ls
6379.conf  sentinel.conf
[root@localhost redis]# vim /etc/redis/sentinel.conf
port 26379     //21 行,监听端口号
daemonize yes    //26行,开启守护进程
pidfile /var/run/redis-sentinel.pid   //31行,PID文件位置
logfile "/var/log/sentinel.log"    //36行,日志文件位置
dir /var/lib/redis/sentinel   //65行,指定工作目录
sentinel monitor mymaster 192.168.10.10 6379 2   //84行,指定监控的 master 地址及端口号
#---------------插入下面两条优化配置------------------------#
min-slaves-to-write 1    ##最小slave数为1,表示至少有1台slave
min-slaves-max-lag 10    ##数据复制和同步的延迟不能超过 10 
[root@localhost ~]# mkdir -p /var/lib/redis/sentinel   ##创建配置文件中指定的工作目录

----------因为三台哨兵节点的配置相同,因此将配置文件scp过去,在创建工作目录即可----------------
[root@localhost ~]# scp -p /etc/redis/sentinel.conf root@192.168.10.50:/etc/redis/sentinel.conf
[root@localhost ~]# scp -p /etc/redis/sentinel.conf root@192.168.10.60:/etc/redis/sentinel.conf
----------------------------------------------------------------------------------------
[root@localhost ~]# redis-sentinel /etc/redis/sentinel.conf    ##redis-sentinel命令指定配置文件,开启哨兵模式
[root@localhost ~]# netstat -anpt |grep 26379    ##查看端口状态
tcp        0      0 0.0.0.0:26379           0.0.0.0:*               LISTEN      8155/redis-sentinel 

2.哨兵模式开启后,配置文件自动进行修改

sentinel myid b8968ce4b0af03b99b387b2e8d2880e23e1c8673   //84行,自动分配密文ID
……省略部分 
######并且在文件结尾部分会自动生成下列信息,指明slav地址及其他两台哨兵地址及ID密文
protected-mode no
sentinel known-replica mymaster 192.168.10.20 6379
sentinel known-replica mymaster 192.168.10.30 6379
sentinel known-sentinel mymaster 192.168.10.60 26379 0cca768420585707028ca7371c266472692dcac8
sentinel known-sentinel mymaster 192.168.10.40 26379 8322b2583d5af36eeb93ae3a810c6ec7846037fd
sentinel current-epoch 0

3.从哨兵端口进入redis客户端,利用info命令查看监控的群集信息

[root@localhost ~]# redis-cli -p 26379
127.0.0.1:26379> info
# Server
redis_version:5.0.10    ##version号
redis_git_sha1:00000000
……省略部分
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.10.10:6379,slaves=2,sentinels=3   ##可以查看到监控的 master ip,以及salve的个数,哨兵的个数

4.验证哨兵模式高可用

4.1 关闭master服务器,模拟故障

[root@localhost ~]# redis-cli   
192.168.10.10:6379> shutdown       ##关闭master

4.2 进入哨兵客户端查看主从信息

[root@localhost ~]# redis-cli -p 26379
127.0.0.1:26379> info
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.10.30:6379,slaves=2,sentinels=3    ##已经完成了故障转换,主服务器master变为192.168.10.30(原为192.168.10.20
127.0.0.1:26379> 

4.3 在新master上写入数据测试

[root@localhost ~]# redis-cli -h 192.168.10.30 
192.168.10.30:6379> info   ##查看节点信息
# Replication
role:master     ##角色类型是 master
connected_slaves:2     ##连接两个slave
slave0:ip=192.168.10.20,port=6379,state=online,offset=57725,lag=1
slave1:ip=192.168.10.10,port=6379,state=online,offset=57711,lag=1

192.168.10.30:6379> set score 89     ##可以写入数据,已经不是slave的只读状态了
OK
192.168.10.30:6379> get score
"89"

4.4 在另一台仅存的slave上测试主从

[root@localhost ~]# redis-cli -h 192.168.10.20
192.168.10.20:6379> keys *     ##可以查看的新master上插入的键值,确认主从故障切换成功
1) "score"
2) "name"
192.168.10.20:6379> get score
"89"

4.5 查看哨兵节点配置文件末尾信息

[root@localhost ~]# vim /etc/redis/sentinel.conf
protected-mode no
sentinel known-replica mymaster 192.168.10.20 6379    
sentinel known-replica mymaster 192.168.10.10 6379      ##配置文件自动修改,将192.168.10.10(原master)降级为slave
sentinel known-sentinel mymaster 192.168.10.60 26379 0cca768420585707028ca7371c266472692dcac8
sentinel known-sentinel mymaster 192.168.10.40 26379 8322b2583d5af36eeb93ae3a810c6ec7846037fd
sentinel current-epoch 1

4.6 重新开启原master(192.168.10.10)进行主从复制验证

[root@localhost ~]# service redis start
Starting Redis server...
[root@localhost ~]# redis-cli -h 192.168.10.10
192.168.10.10:6379> keys *    ## 宕机间在新master上写入的数据也被同步过来了
1) "name"
2) "score"
192.168.10.10:6379> get score
"89"
192.168.10.10:6379> set ABC 123     ## 再次开启后不会切换回master,不再具有写的权限
(error) READONLY You can't write against a read only replica.

注意点:在配置监控master时指定了quorum数量,若sentinel哨兵群集发生故障,存活的哨兵服务器数量少于quorum数量,那么哨兵群集将失效。不能再进行故障切换

你可能感兴趣的:(数据库管理,redis,网络,数据库,运维)