Redis-day3.2-主从复制

Redis主从复制

1.介绍

Redus集群概念

​ 由于单机Redis存储能力较差,无法实现读写分离、负载均衡、高可用,本篇就介绍Redis集群搭建方案即实现原理,实现Redis对数据的冗余备份,从而保证数据与服务的高可用,主从复制是哨兵和集群的基石,因此循序渐进,先做主从复制。

概述:

主从复制,是指将一台Redis服务器的数据,备份到其他的Redis服务器;

主从是哨兵和集群模式能够实施的基础,前者为主节点(master),后者为从节点(slave),只能由主节点到从节点;默认一个主节点可有多个从节点,但一个从节点只能有一个主节点,主节点负责接收写请求,从节点负责读请求,从而实现读写分离;

主从一般部署在不同机器上,复制时若存在网络延时问题,可使用 repl-disable-tcp-nodelay 选择是否关闭 TCP_NODELAY,默认为关闭:

​ 关闭:无论数据大小都会及时同步到从节点,占带宽,适用于主从网络好的场景。
​ ​ 开启:主节点每隔指定时间合并数据为 TCP 包节省带宽,默认为 40 毫秒同步一次,适用于网络环境复 杂或带宽紧张,如跨机房。

2.主从复制原理详解

主从复制过程大体可以分为 3 个阶段(系统自动执行):

  • 连接建立阶段
  • 数据同步阶段
  • 命令传播阶段

1)连接建立阶段

  • 连接建立阶段即准备阶段

该阶段的主要作用是在主从节点之间建立连接,为数据同步做好准备:

1> 保存主节点信息

​ 从节点服务器内部维护了两个字段,即masterhost和masterport字段,用于存 储主节点的ip和port信息;

​ 需要注意的是,slaveof是异步命令,从节点完成记录主节点ip和port的保存 后,向发送slaveof命令的客户端直接返回OK,实际的复制操作在这之后才开始进行。

2> 主从建立 socket 连接

​ 定时发现主节点以及尝试建立连接,从节点每秒1次调用复制定时函数replicationCron(),如果发现了有主节点可以连接,便会根据主节点的ip和port,创建socket连接。如果连接成功,则:

  • 从节点:
为该socket建立一个专门处理复制工作的文件事件处理器,负责后续的复制工作,如
接收RDB文件、接收命令传播等。
  • 主节点:
接收到从节点的socket连接后(即accept之后),为该socket创建相应的客户端状
态,并将从节点看做是连接到主节点的一个客户端,后面的步骤会以从节点向主节点
发送命令请求的形式来进行。
3> 发送ping命令

​ 从节点成为主节点的客户端之后,发送ping命令进行首次请求,目的是:检查 socket连接是否可用,以及主节点当前是否能够处理请求。

  • 发送ping后,会出现3中情况

    1. 返回pong

      ​ 说明socket连接正常,且主节点当前可以处理请求,复制过程继续。

    2. 超时

      ​ 一定时间后从节点仍未收到主节点的回复,说明socket连接不可用,则从节点断开 socket连接,并重连。

    3. 返回pong以外的结果

      ​ 如果主节点返回其他结果,如正在处理超时运行的脚本,说明主节点当前无法处理命 令,则从节点断开socket连接,并重连。

    4. 身份验证

    ​ 如果从节点中设置了masterauth选项,则从节点需要向主节点进行身份验证; 没有设置该选项,则不需要验证。从节点进行身份验证是通过向主节点发送auth 命令进行的,auth命令的参数即为配置文件中的masterauth的值。

    ​ 如果主节点设置密码的状态,与从节点masterauth的状态一致(一致是指都存 在,且密码相同,或者都不存在),则身份验证通过,复制过程继续;如果不一 致,则从节点断开socket连接,并重连。

    1. 发送从节点端口信息

    ​ 身份验证之后,从节点会向主节点发送其监听的端口号(前述例子中为6381、 6382),主节点将该信息保存到该从节点对应的客户端的slave_listening_port字 段中;该端口信息除了在主节点中执行info Replication时显示以外,没有其他作用。

2)数据同步阶段

​ 主从节点之间的连接建立以后,便可以开始进行数据同步,该阶段可以理解为从节点数据的初始化。具体执行的方式是:从节点向主节点发送psync命令 (Redis2.8以前是sync命令),开始同步。

​ 数据同步阶段是主从复制最核心的阶段,根据主从节点当前状态的不同,可以分为全量复制和部分复制。

​ 需要注意的是,在数据同步阶段之前,从节点是主节点的客户端,主节点不是从节点的客户端;而到了这一阶段及以后,主从节点互为客户端。原因在于:在此之前,主节点只需要响应从节点的请求即可,不需要主动发请求,而在数据同步阶 段和后面的命令传播阶段,主节点需要主动向从节点发送请求(如推送缓冲区中的 写命令),才能完成复制。

4)命令传播阶段

​ 数据同步阶段完成后,主从节点进入命令传播阶段;在这个阶段主节点将自己 执行的写命令发送给从节点,从节点接收命令并执行,从而保证主从节点数据的一 致性。

​ 在命令传播阶段,除了发送写命令,主从节点还维持着心跳机制:ping和 replconf ack。

3.主要作用

  1. 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
  2. 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
  3. 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务,分担服 务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发量。
  4. 读写分离:主库写、从库读,读写分离不仅可以提高服务器的负载能力,同时可根据需求的变化,改变从库 的数量。
  5. 高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础。

4.开启主从配置

1)规划

  • 三节点全在master1上做

    • 6379:主节点
    • 6381:从节点
    • 6382:从节点
  • 配置主从可以在命令行或配置文件中配置,上面提到主节点负责写,从节点负责读,因此推荐开启从服务器的只读配置,否则的话在从节点的写操作不会同步到主节点会导致数据不一致。

2)配置从节点

1.复制多份配置文件(准备从节点)
[root@k8s-master1 redis]# cd /usr/local/redis/bin/
[root@k8s-master1 bin]# cp redis.conf redis-6381.conf
[root@k8s-master1 bin]# cp redis.conf redis-6382.conf

2.配置三配置文件(除了端口号不同,其余两条配置要一样)
[root@k8s-master1 bin]# vim redis.conf
[root@k8s-master1 bin]# vim redis-6381.conf
[root@k8s-master1 bin]# vim redis-6382.conf
port 6382	# 更改端口为从节点对应的端口号
aclfile "/usr/local/redis/conf/users.aclfile"	# 注释此行,避免从节点加入主节点时出现 down 问题
"user default on nopass ~* +@all"	# 注释或删除配置文件内提交过的密码行(一般在行末)

3)设置密码的二种方式

  • 也可以不设置密码或用户(不推荐)
  • 登录时命令行指定或进入后切换都可以
1.永久修改密码	# 从节点指定到主节点的用户与密码
[root@k8s-master1 ~]# vim /usr/local/redis/bin/redis-6381.conf
[root@k8s-master1 ~]# vim /usr/local/redis/bin/redis-6382.conf
# masteruser <username>
masteruser Peng
# masterauth <master-password>
masterauth 123

2.临时更新密码(重启服务失效)
127.0.0.1:6379> config set requirepass 123

# 查看密码
127.0.0.1:6379> config get requirepass
1) "123"

3)启动三节点

1.启动三台节点
/usr/local/redis/bin/redis-server /usr/local/redis/bin/redis.conf 
/usr/local/redis/bin/redis-server /usr/local/redis/bin/redis-6381.conf 
/usr/local/redis/bin/redis-server /usr/local/redis/bin/redis-6382.conf 

2.查看启动状态
[root@k8s-master1 ~]# ps -elf | grep redis-server
5 S root      96741      1          00:00:00 /usr/local/redis/bin/redis-server 127.0.0.1:6382
5 S root      96879      1          00:00:00 /usr/local/redis/bin/redis-server 127.0.0.1:6381
5 S root      96906      1          00:00:00 /usr/local/redis/bin/redis-server 127.0.0.1:6379
0 S root      97051  66502          00:00:00 grep --color=auto redis-serve

3.查看启动端口
[root@k8s-master1 ~]# netstat -lntp | grep redis
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      96906/redis-server  
tcp        0      0 127.0.0.1:6381          0.0.0.0:*               LISTEN      96879/redis-server  
tcp        0      0 127.0.0.1:6382          0.0.0.0:*               LISTEN      96741/redis-server  

4)从节点上加入集群

  • 将从节点加入到主节点
加入接点状态:
	up		# 链接成功
	down	# 链接失败,原因是acl权限影响了主从复制

将从节点加入到主节点:6379

1.加入从节点1:6381
[root@k8s-master1 ~]# redis-cli --user Peng -p 6381
127.0.0.1:6381> slaveof 127.0.0.1 6379
OK
127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up	# up为加入成功
···

2.加入从节点2:6382
[root@k8s-master1 ~]# redis-cli --user Peng -p 6382
127.0.0.1:6382> slaveof 127.0.0.1 6379
OK
127.0.0.1:6382> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up	# up为加入成功
···

3.主节点6379:查看加入状态
[root@k8s-master1 ~]# redis-cli --user Peng
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2		# 已加入2个从节点
slave0:ip=127.0.0.1,port=6381,state=online,offset=4676,lag=1
slave1:ip=127.0.0.1,port=6382,state=online,offset=4676,lag=0

image-20210506191612385

5)测试从库只读

Redis主从复制读写分离图

image-20210506202725550

6)处理网络波动

​ repl-disable-tcp-nodelay no:该配置作用于命令传播阶段,控制主节点是否 禁止与从节点的TCP_NODELAY;默认no,即不禁止TCP_NODELAY。当设置为yes时, TCP会对包进行合并从而减少带宽,但是发送的频率会降低,从节点数据延迟增加, 一致性变差;具体发送频率与Linux内核的配置有关,默认配置为40ms。当设置为no 时,TCP会立马将主节点的数据发送给从节点,带宽增加但延迟变小。

​ 一般来说,只有当应用对Redis数据不一致的容忍度较高,且主从节点之间网络 状况不好时,才会设置为yes;多数情况使用默认值no。

7)大体流程

  1. 保存主节点信息:配置slaveof之后会在从节点保存主节点的信息。
  2. 主从建立socket连接:定时发现主节点以及尝试建立连接。
  3. 发送ping命令:从节点定时发送ping给主节点,主节点返回PONG;若主节点没有返 回 ping 或因阻塞无法响应导致超时,则主从断开,在下次定时任务时会从新ping主节 点。
  4. 权限验证:若主节点开启了ACL或配置了requirepass参数,则从节点需要配置 masteruser和masterauth参数才能保证主从正常连接。
  5. 同步数据集:首次连接,全量同步。
  6. 命令持续复制:全量同步完成后,保持增量同步。

全量复制与部分复制

1.全量复制

  • redis 全量复制的原理

    首先将 master 本身的 RDB 文件同步给 slave,而在同步期间,master 写入的命令 也会记录下来(master 内部有一个复制缓冲区,会记录同步时 master 新增的写入),当 slave 将 RDB 加载完后, 会通过偏移量的对比将这期间 master 写入的值同步给 slave。

  • 全量复制的开销

    1. bgsave 的开销,每次 bgsave 需要 fork 子进程,对内存和 CPU 的开销很大
    2. RDB 文件网络传输的时间(网络带宽)
    3. 从节点清空数据的时间
    4. 从节点加载 RDB 的时间
    5. 可能的 AOF 重写时间(如果我们的从节点开启了 AOF,则加载完 RDB 后会对 AOF 进行一个重写,保证 AOF 是最新的)

image-20210506203714769

2.部分复制

​ 当 master 和 slave 断开连接时,master 会将期间所做的操作记录到复制缓存区当中(可以看成是一个队列, 其大小默认 1M)。待 slave 重连后,slave 会向 master 发送 psync 命令并传入 offset 和 runId,此时若 master 发现 slave 传输的偏移量的值,在缓存区队列范围中,就会将从 offset 开始到队列结束的数据传给 slave,从而达到同步,降低了使用全量复制的开销。

3.主从复制存在的问题

  1. 手动故障转移
  2. 写能力和存储能力受限
posted @ 2022-06-09 18:18  秋风お亦冷  阅读(35)  评论(0)    收藏  举报