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中情况
-
返回pong
说明socket连接正常,且主节点当前可以处理请求,复制过程继续。
-
超时
一定时间后从节点仍未收到主节点的回复,说明socket连接不可用,则从节点断开 socket连接,并重连。
-
返回pong以外的结果
如果主节点返回其他结果,如正在处理超时运行的脚本,说明主节点当前无法处理命 令,则从节点断开socket连接,并重连。
-
身份验证
如果从节点中设置了masterauth选项,则从节点需要向主节点进行身份验证; 没有设置该选项,则不需要验证。从节点进行身份验证是通过向主节点发送auth 命令进行的,auth命令的参数即为配置文件中的masterauth的值。
如果主节点设置密码的状态,与从节点masterauth的状态一致(一致是指都存 在,且密码相同,或者都不存在),则身份验证通过,复制过程继续;如果不一 致,则从节点断开socket连接,并重连。
- 发送从节点端口信息
身份验证之后,从节点会向主节点发送其监听的端口号(前述例子中为6381、 6382),主节点将该信息保存到该从节点对应的客户端的slave_listening_port字 段中;该端口信息除了在主节点中执行info Replication时显示以外,没有其他作用。
-
2)数据同步阶段
主从节点之间的连接建立以后,便可以开始进行数据同步,该阶段可以理解为从节点数据的初始化。具体执行的方式是:从节点向主节点发送psync命令 (Redis2.8以前是sync命令),开始同步。
数据同步阶段是主从复制最核心的阶段,根据主从节点当前状态的不同,可以分为全量复制和部分复制。
需要注意的是,在数据同步阶段之前,从节点是主节点的客户端,主节点不是从节点的客户端;而到了这一阶段及以后,主从节点互为客户端。原因在于:在此之前,主节点只需要响应从节点的请求即可,不需要主动发请求,而在数据同步阶 段和后面的命令传播阶段,主节点需要主动向从节点发送请求(如推送缓冲区中的 写命令),才能完成复制。
4)命令传播阶段
数据同步阶段完成后,主从节点进入命令传播阶段;在这个阶段主节点将自己 执行的写命令发送给从节点,从节点接收命令并执行,从而保证主从节点数据的一 致性。
在命令传播阶段,除了发送写命令,主从节点还维持着心跳机制:ping和 replconf ack。
3.主要作用
- 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
- 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
- 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务,分担服 务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发量。
- 读写分离:主库写、从库读,读写分离不仅可以提高服务器的负载能力,同时可根据需求的变化,改变从库 的数量。
- 高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础。
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
5)测试从库只读
6)处理网络波动
repl-disable-tcp-nodelay no:该配置作用于命令传播阶段,控制主节点是否 禁止与从节点的TCP_NODELAY;默认no,即不禁止TCP_NODELAY。当设置为yes时, TCP会对包进行合并从而减少带宽,但是发送的频率会降低,从节点数据延迟增加, 一致性变差;具体发送频率与Linux内核的配置有关,默认配置为40ms。当设置为no 时,TCP会立马将主节点的数据发送给从节点,带宽增加但延迟变小。
一般来说,只有当应用对Redis数据不一致的容忍度较高,且主从节点之间网络 状况不好时,才会设置为yes;多数情况使用默认值no。
7)大体流程
- 保存主节点信息:配置slaveof之后会在从节点保存主节点的信息。
- 主从建立socket连接:定时发现主节点以及尝试建立连接。
- 发送ping命令:从节点定时发送ping给主节点,主节点返回PONG;若主节点没有返 回 ping 或因阻塞无法响应导致超时,则主从断开,在下次定时任务时会从新ping主节 点。
- 权限验证:若主节点开启了ACL或配置了requirepass参数,则从节点需要配置 masteruser和masterauth参数才能保证主从正常连接。
- 同步数据集:首次连接,全量同步。
- 命令持续复制:全量同步完成后,保持增量同步。
全量复制与部分复制
1.全量复制
-
redis 全量复制的原理
首先将 master 本身的 RDB 文件同步给 slave,而在同步期间,master 写入的命令 也会记录下来(master 内部有一个复制缓冲区,会记录同步时 master 新增的写入),当 slave 将 RDB 加载完后, 会通过偏移量的对比将这期间 master 写入的值同步给 slave。
-
全量复制的开销
- bgsave 的开销,每次 bgsave 需要 fork 子进程,对内存和 CPU 的开销很大
- RDB 文件网络传输的时间(网络带宽)
- 从节点清空数据的时间
- 从节点加载 RDB 的时间
- 可能的 AOF 重写时间(如果我们的从节点开启了 AOF,则加载完 RDB 后会对 AOF 进行一个重写,保证 AOF 是最新的)
2.部分复制
当 master 和 slave 断开连接时,master 会将期间所做的操作记录到复制缓存区当中(可以看成是一个队列, 其大小默认 1M)。待 slave 重连后,slave 会向 master 发送 psync 命令并传入 offset 和 runId,此时若 master 发现 slave 传输的偏移量的值,在缓存区队列范围中,就会将从 offset 开始到队列结束的数据传给 slave,从而达到同步,降低了使用全量复制的开销。
3.主从复制存在的问题
- 手动故障转移
- 写能力和存储能力受限