Redis(五):Redis主从复制原理及其部署

Redis主从复制原理及其部署

  • Redis主从复制如何实现?为什么?存在问题有哪些?解决方案是什么?

Redis的主从复制

(1)主从复制的目的

  • 机器故障:(可用性)如何保证数据同步。
  • 容器瓶颈:读写分离,扩容需求
  • 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
  • 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
  • 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
  • 读写分离:可以用于实现读写分离,主库写、从库读,读写分离不仅可以提高服务器的负载能力,同时可根据需求的变化,改变从库的数量;
  • 高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。

总结下:数据的冗余备份;机器故障时的快速回复;负载(读请求可以请求到多个Slave,减小单个Redis的并发量)读写分离;实现数据的高可用。

(2)主从复制原理

  1. 从节点执行 slaveof 命令
  2. 从节点只是保存了 slaveof 命令中主节点的信息,并没有立即发起复制
  3. 从节点内部的定时任务发现有主节点的信息,开始使用 socket 连接主节点
  4. 连接建立成功后,发送** ping 命令**,希望得到** pong 命令响应**,否则会进行重连
  5. 如果主节点设置了权限,那么就需要进行权限验证;如果验证失败,复制终止。
  6. 权限验证通过后,进行数据同步,这是耗时最长的操作,主节点将把所有的数据全部发送给从节点。
  7. 当主节点把当前的数据同步给从节点后,便完成了复制的建立流程。接下来,主节点就会持续的把写命令发送给从节点,保证主从数据一致性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MfXGH2lN-1588256828570)(E423F613AC8A45CF992C14CA73763745)]

可以分为两个过程,一个是连接过程,一个是数据复制过程

  • 连接过程:slaveof命令保存主节点,socket进行主节点的连接(轮询ping命令,得到pong命令返回则表示连接成功);验权(主节点有权限校验的情况下,slaver节点需配置masterauth)
2-1. 连接过程

连接不成功的处理

从节点执行info replication查看 master_link_down_since_seconds指标,它会记录与主节点连接失败的系统时间。

ping 请求的主要作用:

  • 检测主从之间网络套接字是否可用。
  • 检测主节点当前是否可接受处理命令。

权限验证

如果主节点设置了requirepass 参数,则需要密码验证,从节点必须配置 masterauth参数保证与主节点相同的密码才能通过验证

2-2. 复制过程
数据同步

先了解下面三个名词概念

  • 主节点保存各从节点复制偏移量(offset)
    • 从节点每秒钟会上报自己的复制偏移量(心跳机制);主节点也会进行复制偏移量的保存。作用主要有两个,一:主节点知道从节点复制位置,部分复制时,以复制偏移量为开始位置进行复制;二:判断主从节点数据是否一致的依据。
    • 通过 info replication 命令查看master_repl_offset
  • 主节点复制积压缓存区
    • 复制积压缓冲区是一个保存在主节点的一个固定长度的先进先出的队列。默认大小 1MB。
    • 作用:用于部分复制和复制命令丢失的数据补救
  • 主节点运行ID
    • 运行 ID 的主要作用是用来识别 Redis 节点(40位)
    • 问题在于,主节点运行ID改变时,会导致全量复制的发生
    • 解决方法:debug reload命令重新加载 RDB 并保持运行 ID 不变。从而有效的避免不必要的全量复制。缺点是阻塞当前Redis节点主线程。
Redis 同步有 2 个命令:sync和psync

前者是 redis 2.8 之前的同步命令,后者是 redis 2.8 为了优化 sync 新设计的命令。我们会重点关注 2.8 的 psync 命令。

命令格式为 psync {runId} {offset}

runId : 从节点所复制主节点的运行 id

offset:当前从节点已复制的数据偏移量

知乎上盗的一张图(知乎很好用)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jq6in3wz-1588256828573)(6A7B035C68654B5D953381AA27751DA1)]

大致说明下:从节点发送 psync 命令给主节点,runId 就是目标主节点的 ID,如果没有默认为 -1,offset 是从节点保存的复制偏移量,如果是第一次复制则为 -1.

Redis同步-全量复制与部分复制

全量复制是 Redis 最早支持的复制方式,也是主从第一次建立复制时必须经历的的阶段。触发全量复制的命令是 sync 和 psync。之前说过,这两个命令的分水岭版本是 2.8,redis 2.8 之前使用 sync 只能执行全量不同,2.8 之后同时支持全量同步和部分同步

全量复制流程如下:

知乎上盗的一张图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CqSahG0C-1588256828577)(8F32F61DF85A482FA44B3E7FB62B454D)]

  1. 发送** psync 命令(spync ? -1)**
  2. 主节点根据命令返回 FULLRESYNC
  3. 从节点记录主节点 ID 和 offset
  4. 主节点 bgsave 并保存 RDB 到本地
  5. 主节点发送 RBD 文件到从节点
  6. 从节点收到 RDB 文件并加载到内存中
  7. 主节点在从节点接受数据的期间,将新数据保存到**“复制客户端缓冲区”**,当从节点加载 RDB 完毕,再发送过去。(如果从节点花费时间过长,将导致缓冲区溢出,最后全量同步失败)
  8. 从节点清空数据后加载 RDB 文件,如果 RDB 文件很大,这一步操作仍然耗时,如果此时客户端访问,将导致数据不一致,可以使用配置slave-server-stale-data关闭.
  9. 从节点成功加载完 RBD 后,如果开启了 AOF,会立刻做 bgrewriteaof。

注:Redis 的默认超时机制(60 秒),会导致全量复制失败。可以通过调大 repl-timeout 参数来解决此问题。

部分复制流程如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u0euF5FZ-1588256828581)(59776A4219F142E1B2F0CEC7AB96636B)]

  1. 当从节点出现网络中断,超过了** repl-timeout 时间**,主节点就会中断复制连接
  2. 主节点会将请求的数据写入到“复制积压缓冲区”,默认 1MB。
  3. 当从节点恢复,重新连接上主节点,从节点会将 offset 和主节点 id 发送到主节点
  4. 主节点校验后,如果偏移量的数后的数据在缓冲区中,就发送 cuntinue 响应 —— 表示可以进行部分复制
  5. 主节点将缓冲区的数据发送到从节点,保证主从复制进行正常状态。

注意事项:

Redis 在 2.8 版本退出了类似增量复制的 psync 命令,当 Redis 主从直接发生了网络中断,不会进行全量复制,而是将数据放到缓冲区(默认 1MB)里,在通过主从之间各自维护复制 offset 来判断缓存区的数据是否溢出,如果没有溢出,只需要发送缓冲区数据即可,成本很小,反之,则要进行全量复制,因此,控制缓冲区大小非常的重要。修改repl-backlog-size参数实现

(3)如何部署Redis的主从

这里我会介绍两种安装方式,一种是非Docker部署,一种是Docker部署,让诸君看看Docker的魅力;真香!

非Docker部署的关键是配置文件的修改,Docker部署将配置文件的修改要么使用镜像文件替代,要么是启动容器时使用对应的参数和将本地文件挂载到Redis容器数据卷中,实现动态地配置;Docker在这里就是起到了简化部署过程的作用!很香!

1. 非Docker部署

根据服务器性能,以及项目中实际业务需求,选择Master(主节点),slaver(从节点)。

F道友演示的,是在同一台虚机上,所以iptable的设置在此省略;使用不同的端口来进行演示。

类型 角色 IP 端口
Redis master 192.168.30.134 6379
Redis slaver 192.168.30.134 6380
Redis slaver 192.168.30.134 6381
Redis slaver 192.168.30.134 6382

redis.config配置文件参数设置如下

# 包含文件(redis-base.conf,文件从redis安装目录中拷贝的)
include /data/soft/redis-sentinel/redis-base.conf
# 将redis-base.conf文件中,bind注释,需要在外网访问,将protected-model改为no
protected-mode no
# 端口 从节点的端口需要修改
port 6379
# 绑定主机 (或者不配置-自己在单个虚机上练习要注意这一点)
bind 0.0.0.0
# 后台运行
daemonize yes
# pid文件
pidfile redis_master.pid
# 日志文件
logfile "/data/log/redis-sentinel-log/redis-17007-log/redis-17007.log"
# 主认证密码
masterauth 123456
# 认证密码
requirepass 123456
# 最大内存10M,一般为机器内存的3/4
maxmemory 10mb
# 内存达到最大时策略,可选择其他策略
maxmemory-policy volatile-lru
# 目录(Data存放路径,虚机练习时不要相同)
dir /data/soft/redis-sentinel/redis-master/
# 快照文件(可使用默认)
dbfilename dump-master.rdb
# 开启AOF(热备,减少宕机等情况下数据丢失)
appendonly yes
# 更新指定的日志文件名,默认为appendonly.aof
appendfilename appendonly.aof
# AOF执行间隔 
# no:表示等操作系统进行数据缓存同步到磁盘(快)     
# always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
# everysec:表示每秒同步一次(折衷,默认值)
appendfsync everysec
# 下面是核心的主从配置(配置在从节点上,重要的事情说三遍:配置在从节点上
# 配置在从节点上,配置在从节点上)
# 从节点要跟随的主节点
slaveof 192.168.30.134 6379
# 主节点认证密码,如果设置了密码,就要设置
masterauth 123456
# 配置后从节点只能读(读写分离时使用)
slave-read-only yes

还有一些slace的配置,因为这里是做演示,所以不一一列出,有兴趣的看我另一篇相关博文。

执行命令如下:

// 主、从节点的配置文件修改成功后,启动相应的Redis服务
// 这里要确定两点:一如果是在两台机器上,确定网络端口是否开放iptable查看对应
// 开放端口信息;二先启动Master服务,再启动从节点服务(否则主从连接失败)
// config/master-6379.conf 是以指定的配置文件(master-6379.conf)启动Redis
./src/redis-server config/master-6379.conf 
2. Docker部署(Docker大法好)

虚机的安装,linux操作系统的安装,docker的安装的过程这里暂且不讲,CSDN,知乎等有大量教程,自行学习。博主以后也会更新一篇,单机版玩转分布式的专栏,里面会讲到上述配置。各位道友,敬请期待!

Redis 镜像文件的获取;这里提供两种方式,一种直接从镜像仓库中pull,一种直接创建,(推荐自行创建,镜像文件的创建是docker很重要的一点,建议一点点学习!)

# 第一种获取镜像方式 -创建镜像
// 个人习惯,我习惯将镜像文件放在local下创建自己的文件夹下
[root@localhost usr]# cd /usr/local/floatcloud/
// 创建镜像文件
[root@localhost floatcloud]# touch Dockerfile
// 编辑镜像文件
[root@localhost floatcloud]# vim Dockerfile 

// Redis镜像文件的内容如下

# 镜像的根本依赖,也可以说是基于centos最新镜像
FROM centos:lastest
# 构建镜像作者
MAINTAINER floatCloud
# 添加用户组、用户
RUN groupadd -r redis && useradd -r -g redis redis
# 更新yum源,linux的epel-release(前面讲过安装docker时,要先安装epel);安装Redis
RUN yum -y update && yum -y install epel-release && yum -y install redis
# 定义端口
EXPOSE 6379

// 创建镜像,查看镜像
// 这个. 很关键,表示的是上下文关系
[root@localhost floatcloud]# docker build -t redis .
[root@localhost floatcloud]# docker images -a

# 第二种获取镜像方式 -pull镜像仓库中的镜像
// 从镜像仓库中搜索镜像
[root@localhost floatcloud]# docker search redis
// docker pull 镜像名:tags      注:tags用来标记镜像不同版本-对应Redis不同版本
// 道友们,可以去https://hub.docker.com/ 中查看自己想下载的版本(不加tags使用的默认版本)
[root@localhost floatcloud]# docker pull redis
[root@localhost floatcloud]# docker images -a

运行docker,一种使用-v 将本地文件挂载到容器的容器数据卷中,实现数据的共享与同步;还有一种是在进入容器 (exec -it),修改配置文件。道友们可以都尝试下!F道人这里推荐使用挂载到容器数据卷的形式,原因你品,你细品。

# 启动参数形式设置
[root@localhost ~]# docker rum -d --name redis-master --privileged=true --restart always -v /var/user/floatcloud/master/redis.conf:/usr/local/etc/redis/redis.conf -v /var/user/floatcloud/master/data:/data -p 6379:6379 redis
[root@localhost ~]# docker rum -d --name redis-slaver1 --privileged=true --restart always -v /var/user/floatcloud/slaver1/redis.conf:/usr/local/etc/redis/redis.conf -v /var/user/floatcloud/slaver1/data:/data -p 6380:6379 redis
[root@localhost ~]# docker rum -d --name redis-slaver2 --privileged=true --restart always -v /var/user/floatcloud/slaver2/redis.conf:/usr/local/etc/redis/redis.conf -v /var/user/floatcloud/slaver2/data:/data -p 6381:6379 redis
[root@localhost ~]# docker rum -d --name redis-slaver3 --privileged=true --restart always -v /var/user/floatcloud/slaver3/redis.conf:/usr/local/etc/redis/redis.conf -v /var/user/floatcloud/slaver3/data:/data -p 6382:6379 redis
// 修改配置文件
// 一:进入容器修改,二:修改本地文件,重启容器
[root@localhost ~]# docker exec -it redis-master sh
[root@localhost ~]# vim /etc/redis/redis
// 配置文件的修改上面已经说过这里就不赘述
// 修改本地文件,并重启容器
[root@localhost ~]# vim /var/user/floatcloud/master/redis.conf
[root@localhost ~]# docker restart redis-master

这里说下从节点的简要配置

# 从节点要跟随的主节点
slaveof 192.168.30.134 6379
# 主节点认证密码,如果设置了密码,就要设置
masterauth 123456
# 配置后从节点只能读(读写分离时使用)
slave-read-only yes

(4)主从的弊端有哪些?怎么解决?

第一:主节点宕机,则Redis主从不可用。

第二:主从节点的维护全部依赖运维,增加运维成本。

解决方法:开启Redis的哨兵模式,道人会在后续博文中介绍Redis的哨兵模式!

道友们,你们的老婆来了!
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章